Hold-and-modify compression

A photograph usually requires 24 bits (3 bytes) per pixel. One strategy for reducing memory is to reduce the number of bits used to describe the color of each pixel, but that also reduces the number of possible colors that the format can display. A high-resolution image on the Amiga 500 typically consist of a table of 16 colors, which often is a bit too few colors for most photographic images. This is a 24-bit oroginal:

And this is the 4-bit 16-color version, that could be displayed on an Amiga:

In the 16-bit version, each pixel is a 3-byte color description, but in the 4-bit version, each pixel is a reference to a color in a 16-records long table of color. The decrease of memory consumption causes a rather obvious loss in image quality.

Hold-and-modify (HAM) allows for displaying more colors than the 16 colors stored in the table. The Amiga implementation of HAM uses a 16-color palette, and the byte array that make out the image data uses two control bits and four data bits. The control bits decide if the next four bits of the byte describes a color set (an index reference), a red modify, a green modify, or a blue modify. The last two bits per byte are not used.

So, a while a regular 16-color image uses 4 bits per pixel (a reference to a color in the table), a HAM image uses 6 bits per pixel, and if the first two is a color set, then the next four are still just a reference, like all pixels are in a regular 16-color image. But the other control bits indicate that the next four bits carries information on how the pixel color is different from the pixel to the left. It could be that it contains more red or less green, and so on, allowing up to 4096 colors to be displayed.

This method works very well on photographic images, but sharp edges may cause bleeding colors, because any pixel that is not a reference to a color table depends on its neighbor to the left. But the method works well for displaying full color images using only 6 bits per pixel instead of 3 bytes.
The artifact can be observed in this classic HAM animation by Ken Offer (1987):

Character compression per image depth

An image is a two-dimensional array of colored pixels, in this case 200 rows pf 320 pixels (320×200), today typically a 2-dimensional pixel array. Color indexing is the concept of replacing the 24-bit pixels with an 8-bit pointer to a color palette, thus reducing the memory required to represent the image. Character compression is the concept of replacing the pixel matrix with a matrix of references to a palette of 8×8 cells. Fewer bits per pixel results in poorer quality, but higher probability of finding similar 8×8 cells, and therefore a smaller image. More bits per pixel results in higher quality, but less probability of finding similar 8×8 cells, and therefore a larger image. The technique does not work well on photographic images. I use these original images:

1-bit (2 colors)

2-bit (4 colors)

3-bit (8 colors)

4-bit (16 colors)

5-bit (32 colors)

8-bit (256 colors)

In total, a 320×200 (64000) pixels image (8000 bytes) consist of 40×25 (1000) characters. On a blank image, only one of them are unique and needs to be stored. If the image contains just one set pixel, then the image contains two unique characters. One blank and one containing the pixel. Using character compression, the one pixel image requires 2000 bytes for the character index (1000 entries of 2 bytes each), 8 bytes for the empty character and 8 bytes for the character with a pixel. 2016 bytes in total, instead of the 8000 bytes that is required to store a 1-bit 320×200 pixel image.

The first (1-bit) image in this example contains 716 of 1000 unique characters and the 2000-byte index, meaning that the compressed images requires 716×8 + 2000 bytes (7728 bytes). Here is one example of matchig characters:

And here are all the matches highlighted:

By reducing the size of the character, you increase the likelihood to find duplicated character, but you increase the size of the character registry.

The probability of finding duplicate characters decrease when more colors are added (the 8-bit version of the image does not contain any duplicated characters) so a strategy for achieving better compression would be to allow a certain degree of mismatch. If two characters are similar to a certain degree, they can be treated as same. If the threshold for treating two characters as similar is too high, no compression will be achieved. If the threshold is too low, the image will look a bit off.

Uncompressed, the 8-bit image consumes one byte per pixel (not counting the color table of 256 colors). The pixel data requires 64000 (320×200) bytes and the color table requires 768 (256×3) bytes. If we use character compression to reduce the number of unique 8×8 pixel cells from 1000 to 500, the table (1000 entries, 2000 bytes) and 500 unique characters (32000 bytes) and the color palette (768 bytes), we would have reduced the memory required from 64768 bytes to 34768 bytes. However, the uncompressed image might be slightly distorted.

If I only look at average color of the character, these 429 cells are similar enough to be interchanged with another character:

Here is the compressed version of the image. The original 8-bit image consists of a color palette (768 bytes) and a pixel array of 64000 bytes. The compressed version consists of the same color palette, a 2000 byte character index and 571 characters, each requiring 64 bytes (36544 bytes).

Of course, the compression level should be slightly lowered for a perfect result, but there are lots of other measures that can be taken. Similarity can be defined in a more sophisticated way than a close average brightness and hue. For photographic images: The threshold for equality could be higher when the detail level is high (in this case, in the center of the image) and lower when the detail level is low. But for pixeled images, top-down-left-right-scanning is good enough. As a conclusion, this is the same image with a slightly lower compression level, still with room for the previous mentioned possible improvements:

A slightly lower compression level increases the output quality significantly, but I am convinced that a more intelligent compression engine will do an even better job.

Mjukvaran SQLite skrivs av oresonliga idioter

SQLite är en mjukvara för datalagring, skriven i C, som fungerar på i princip vilken enhet som helst, från t.ex. Windows Phone till Linux. Mjukvaran är Public Domain, så företaget som utvecklar den försörjer sig istället på att sälja t.ex. support, tilläggsfunktioner eller drift.

Den utvecklare som ska bidra till den officiella produkten måste leva upp till en uppförandekod på 72 punkter som finns publicerad som en del av dokumentationen på deras hemsida (läst 2018-10-23). T.ex. får man inte mörda (punkt 3), vänsterprassla (punkt 4) eller vara stolt (punkt 34), samtidigt som man måste respektera äldre (punkt 68), älska sina fiender (punkt 31) och älska att fasta (punkt 13).

Jag kan ibland vara naiv och utgå ifrån att mina kompanjoner inte är mördare, och kan därför rentav tycka att det är lite nedlåtande att behöva be någon jag ska jobba med att skriva under på det. Och ska jag vara helt ärlig så har jag över huvudet taget svårt att vara kollega med den sortens människa som antas behöva ha en uppförandekod för att inte mörda. Men om jag kan se bortom det, så vill jag naturligtvis hellre jobba med en humanist än mördare. Så vad har fastan med saken att göra?

Det är nog ingen idé att försöka förstå, för det visar sig att SQLite utvecklas av vidskepliga idioter. T.ex. finns det ingen som bidrar till produkten som inte älskar en 2000 år gammal krigsgud från Mellanöstern (punkt 1) eller som inte ger denna övernaturliga entitet äran för sina egna insatser (punkt 42). Som mjukvaruutvecklare i behov av datalagring bör du fundera på om den som behöver denna uppförandekod, och vidare, den som lever efter denna uppförandekod, är någon som du vill ha att göra med? Över huvudet taget, på något tänkbart vis? I så fall har du problem.

“Mannen på gatan”

Jag ogillar verkligen att SVT använder “mannen på gatan”, men när de väl slänger kameran i ansiktet och frågar, så svarar man. Så den som tittar här, 9:30 minuter in, får veta av mig vilka nyhetskällor som är pålitliga.

Eftersom frågan kom på tal, så måste jag tillstå att jag gillar SVT och jag gillar Sveriges Radio P1. Jag vet om att de är min politiska motståndare, men jag uppskattar deras ambition att leverera objektiv och oberoende samhällsinformation.

Harter-Heighways drakkurva

Harter-Heighways drakkurva är en enkel och vacker linjär fraktal med många intressanta attribut. Dels är dess kontur självrepetitiv och kan pusslas ihop med lika dana konturer på många olika sätt, och linjen som kurvan består av korsar aldrig sig själv, oavsett hur lång drakkurva man väljer att rita. En drakkurva kan beskrivas som en serie av höger- och vänstersvängar. Första iterationen består av en sväng, normalt höger. Alla iterationer efter den första innehåller lika många instruktioner som den föregående, multiplicerat med två och plus 1. Alltså 1, 3, 7, 15, 31, och så vidare. Den första generationen består alltså av en högersväng (H):

H

För att skapa nästa iteration utgår man från den föregående och lägger till svängarna från den, baklänges, samtidigt som man byter ut högersvängar till vänstersvängar (V). Man avgränsar föregående iteration från den nya iterationen med en högersväng, alltså:

HHV

Tecken 1 (H) är första iterationen, nästa tecken 2 (H) är avgränsaren mellan den gamla och nya generationen, och den sista vänstersvängen (V) är vårt H från första iterationen, ersatt med ett V. Vidare, HHV baklänges blir VHH och byter man ut alla H mot V och alla V mot H så får man HVV. Då är generation tre alltså HHV, H som avgränsare och sist HVV.

HHVHHVV

Och så vidare! Nästa generation kompletteras med föregående generation baklänges, med höger ändrat till vänster och vänster ändrat till höger. Och ett H i mitten:

HHVHHVVHHHVVHVV

Ett papper kan vikas som en drakkurva, men inte i särskilt många generationer. I C# skulle man kunna använda en sådan här struktur för att beskriva ett enda steg i drakkurvan.

public struct DragonStep
{
    public DragonStep(bool isRightTurn)
            : this(isRightTurn, false) { }
    public DragonStep(bool isRightTurn,
        bool isIterationSeparator)
    {
        IsRightTurn = isRightTurn;
        IsIterationSeparator = isIterationSeparator;
    }
    public bool IsRightTurn { get; set; }
    public bool IsIterationSeparator { get; set; }
}

Egentligen behövs bara en boolesk egenskap för att hålla reda på om steget representerar en höger- eller vänstersväng, men jag vill hålla reda på var en generation börjar och slutar för att kunna rendera den med olika färger.

Här är listklassen som anropas för att bygga kurvan. Funktionen GetDragonSequence skapar en sekvens av höger och vänster-svängar i form av en lista av strukturen vi nyss såg. När man fått listan, handlar det bara om att välja en startposition och en startriktning, och sedan svänga åt höger eller vänster enligt vad som står i listan.

public class DragonCurveGenerator
{
    public static List<DragonStep> GetDragonSequence(int generations)
    {
        var ret = new List<DragonStep>();
        if (generations <= 0)
            return ret;
        if (generations > 0)
            ret.Add(new DragonStep(true));
        if (generations <= 1)
            return ret;
        for (var i = 1; i < generations; i++)
        {
            var lastGenerationFinalIndex = ret.Count - 1;
            ret.Add(new DragonStep(truetrue));
            for (var x = lastGenerationFinalIndex; x >= 0 ; x--)
                ret.Add(new DragonStep(!ret[x].IsRightTurn));
        }
        return ret;
    }
}

Jag definierar upp de möjliga riktningarna med en enumeration, för enkelhetens skull:

public enum Direction { Up, Right, Down, Left }

Sen är det bara en fråga om att rita kurvan, alltså följa sekvensen av svängar. Här får varje sväng representeras av en pixel. Notera att jag utnyttjar avgränsaren mellan iterationer för färgsättning.

public class DragonCurveRenderer
{
    public static void Draw(List<DragonStep> steps,
        Graphics g, Point startPosition, Direction startDirection,
        Brush color1, Brush color2, int first)
    {
        if (steps == null || steps.Count <= 0)
            return;
        var direction = startDirection;
        var x = startPosition.X;
        var y = startPosition.Y;
        var color = color1;
        var index = 0;
        foreach (var step in steps)
        {
            if (step.IsIterationSeparator)
            {
                color = color == color1 ? color2 : color1;
                index++;
            }
            if (index >= first)
                g.FillRectangle(color, x, y, 1, 1);
            ApplyDirection(direction, ref x, ref y);
            if (step.IsRightTurn)
            {
                if ((int) direction < 3)
                    direction++;
                else
                    direction = Direction.Up;
            }
            else
            {
                if (direction > 0)
                    direction--;
                else
                    direction = Direction.Left;
            }
        }
    }
    private static void ApplyDirection(Direction direction,
        ref int x, ref int y)
    {
        switch (direction)
        {
            case Direction.Up:
                y--;
                break;
            case Direction.Right:
                x++;
                break;
            case Direction.Down:
                y++;
                break;
            case Direction.Left:
                x--;
                break;
            default:
                throw new ArgumentOutOfRangeException();
        }
    }
}

Bilden föreställer en drakkurva på 18 generationer där generation 6 (med index 5) är den förste som ritas ut. Alltså totalt 13 fält, varannan är vit, varannan är svart. Så här kan användningen se ut (Windows Forms):

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace DragonCurve
{
    public partial class Form1 : Form
    {
        private List<DragonStep> DragonSteps { get; set; }
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            DragonSteps = DragonCurveGenerator.GetDragonSequence(18);
        }
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            var startPoint = new Point(550, 450);
            DragonCurveRenderer.Draw(DragonSteps, e.Graphics,
                startPoint, Direction.Up, Brushes.White, Brushes.Black, 5);
        }
    }
}

E.T. for Atari 2600

The Atari 2600 was a home gaming console from 1977. The 2600 was a rather primitive machine compared to the later Commodore 64 (1982), but it supported hardware sprites and color graphics, which the Sinclair ZX didn’t. But the introduction price was rather high. $199 back then corresponds to more than $800 today.

Many games were released for the 2600, but one of the most talked about, E.T., was a huge commercial failure. You play as the alien E.T. on Earth, and the objective of the game is to help E.T. get home. Every move you make costs energy, but you can pick up pieces of candy to gain energy.

First, you need to pick up three parts that make up a special phone that can be used to contact the home planet. You can swap 9 pieces of candy for a part, if you like. The parts are found in pits that you fall into, and can levitate out of. To levitate, press fire so that E.T.’s neck is stretched, and when the neck is stretched, you simply levitate higher by pushing the joystick forward.

E.T. has three lives. E.T.’s friend Elliot can bring him back to life when he dies. There is a special object that persuades Elliot to give E.T. a fourth life if it is carried. The game contains two protagonists, a scientist and an FBI agent, who can capture E.T. or steal phone parts from him. If you manage to find all three phone parts, you need to locate a place where the phone works. And after finding this place, you have to locate the place where the spaceship lands, and stay there and await the ship. If you succeed, you progress to the next level where the objective is the same, but the conditions are harder.

The game looks quite good for its time, but it is it is rather buggy and unpredictable. You can fall into a pit without any warning, and it is sometimes rather hard to get out of a pit without falling in again. The best thing about this game, is that you can chat with a friend while playing – the game does not require full attention. This video shows how to complete the first level:

Grisen i säcken

26 år har passerat sedan Galenskaparna och Aftershave hade premiär med sin revy Grisen i säcken, och jag har precis sett om den versionen jag bandade på VHS i mitten av 90-talet. Revyn består av tre akter, där akt två och tre håller det format som vi är vana att se från gruppen – ett slags sofistikerat studentspex. Men det är första akten som gör denna revy speciell, och därför lämnar jag övrigt okommenterat. Den första akten är en sammanhängande musikal som gruppen själva beskriver som en dansbandsopera, viket flörtar med den för tiden populära genren rock opera, som representerades av t.ex. Pete Townshend, Savatage, Dave Clark och Styx.

Den utspelar sig 1991, vilket var året revyn hade premiär. 1991 var ett turbulent år i politiken. Ekonomin hade kraschat och stödet Socialdemokraterna var lågt. De förlorade makten till Moderaterna under Carl Bildt. Kristdemokraterna kom in i riksdagen, tillsammans med missnöjespartiet Ny Demokrati som styrdes av Ian Wachtmeister och Bert Karlsson. Det är Ny Demokratis uppgång och fall som utgör handlingen för akten – eller möjligtvis partiet Ny Deodorant som existerar i ett parallellt universum, under ledning av Rune och sedermera greven Douglas. Att Rune motsvarar Bert och Douglas motsvarar Ian är helt uppenbart för den som sett Grisen i säcken, men jag nämner det ifall du inte sett den och ändå vill förstå vad jag pratar om.

Budskapet i första akten är fortfarande aktuellt, och många händelser går att applicera på Sverigedemokraterna, men förutsättningarna är helt annorlunda. Bert och Ian (och så även Rune och Douglas) var företagsamma och mer eller mindre framgångsrika entreprenörer, medan Sverigedemokrater är frustrerade gräsrötter, helt utan tidigare erkännande i samhället de verkar i. Ny Demokrati (och även Ny Deodorant) havererade redan under första mandatperioden.

Rimligen kan inte Galenskaparna och Aftershave ha känt till hur historien om Ny Demokrati skulle sluta, när de lät sitt fiktiva parti Ny Deodorant haverera – Rune och Douglas blev tillslut programledare i tv. I valet 1994 fick Ny Demokrati 1,4 procent av väljarstödet och både Bert och Ian hoppade av. Ian fick en talkshow på TV3, “I grevens tid”, medan det gullades med Bert i Melodifestivalen – inget förlåter rasistisk politik som exploaterandet av unga artister.

När jag såg Grisen i säcken för första gången var jag V-väljare, och jag applåderade den politiska träffsäkerheten. Idag tillhör jag den politiska mitten, men tycker ändå att detta verk har åldrats väl. Jag behöver inte hålla med om allt för att förstå Claes Erikssons briljanta manus och gruppens utmärkta framförande. Men med det sagt, så delar jag förmodligen Erikssons syn på Ny Demokrati. Och kanske även på Sverigedemokraterna, men det vet jag egentligen inte.

Spaning: Framtiden för handdatorn

Min första mobiltelefon var någon gammal Ericsson som både lät mig ringa (för hutlös minuttaxa) och skicka SMS. Min första handdator* var en svartvit Sony CLIÉ med Palm OS. Den virtuella upplösningen var 320 x 320 punkter, men den fysiska upplösningen var på 640 x 640 punkter, vilket innebar att den kunde återge vektorgrafik och text betydligt bättre än bitmapsbilder. Dessutom kunde den visa 16 gråskalor. Man kunde surfa på Internet genom att koppla den till sin PC:s USB-bort och ladda hem de sidor man ville läsa senare under dagen.

Idag har dessa två enheter fusionerats till en enda enhet, som i princip är en handdator med en ringfunktion**. Många har försökt, men det var Apple som lyckades göra denna nya produkt till en kommersiell succé i slutet på 00-talet. När man idag säger “mobil” eller “telefon” så menar man en handdator som har ringfunktion (som numera knappt används). Vill man förtydliga, kan man säga “smart telefon”, men idag är det nästan som att säga “platt-tv”.

Det var inte förrän Apple gav sig in i leken som handdatorn med ringfunktion blev var mans ägo, och det var inte heller förrän Apple gav sig in i leken med produkten iPad som “surfplattan” blev en kommersiellt framgångsrik produkt. Skillnaden mellan en smart telefon och en surfplatta är att surfplattan saknar ringfunktion, och är därmed alltså en handdator.

När Microsoft på allvar ger sig in i matchen med en surfplatta uppstod förvirringen på allvar. Microsofts Surface Pro saknar tangentbord, precis som iPad, och den har touchscreen precis som iPad. Men eftersom den levereras med bättre anslutningsmöjligheter till andra enheter och med ett bredare utbud av mjukvara antas den istället vara “en dator”, vilket omkullkastar allt jag hittills sagt.

För rent tekniskt, är inte en surfplatta en telefon utan ringfunktion, utan en dator. Precis på samma sätt som en smartphone faktiskt är en dator med ringfunktion. Och eftersom dessa enheter är datorer, så är det hårdvaran och operativsystemet som påverkar deras användbarhet. En iPad har ett operativsystem (IOS) som utvecklats för informationskonsumenter, som sakta rör sig mot att även kunna tillgodose producenter. En Surface Pro har ett operativsystem som utvecklats för informationsproducenter, som sakta för sig mot att även tillgodose konsumenter. Men det är fortfarande datorer!

Nu när intresset för att ringa telefonsamtal har minskat, och Nokia släppt en traditionell mobiltelefon som kostar några hundralappar, ser jag två potentiella konsekvenser. För det första tror jag att intresset för telefoni minskar bland både producenter och konsumenter av dyra handdatorer. För det andra tror jag att den som vill kunna ringa, i framtiden kommer att köpa en telefon (i ordets traditionella bemärkelse), typ en Nokia 3310.

Apples enorma framgång med iPhone kommer göra att det annalkande paradigmskiftet dröjer, men när det väl kommer, tror jag att det innebär att den lilla handdatorn tappar sin ringfunktion, men erhåller egenskaper som gör att den ersätter PC:n. När man kör Visual Studio, Cubase, SQL Server, med mera, i sin “telefon man inte kan ringa med”, så är det “telefonen” man dockar in till skärm och tangentbord på jobbet. Men det är inte den man kommer att ringa med. Om man vill ringa, så köper man en Nokia 3310.

*) En handdator är en mycket portabel dator – så pass portabel att den kan bäras i en hand när den är i drift. En handdator har tryckkänslig skärm (touchscreen) och möjlighet till batteridrift.

**) Inte ens respektabla Cambridge Dictionary innehåller en definition av ett telefonsamtal (alltså nyttjandet av en ringfunktion), utan nöjer sig med att säga att ett telefonsamtal är vad som sker när man “använder en telefon”.

Mac vs. PC

MacWorld presenterar “11 klockrena argument” för att Mac är bättre än PC. Rent tekniskt är en Mac en PC från Apple, men det som menas här är att en Mac är bättre än en annan PC, som t.ex. en Microsoft Surface, en HP Elitebook eller en Chromebook. För detta levereras 11 “klockrena” argument (som alla utom det 4:e är korrekta), vars styrka och kvalité jag tänker nosa lite på, genom att jämföra dem med Microsoft.

1. Mac OS främjar hälsan

När OS X var nytt, var det extremt buggigt, men nu är det hyfsat stabilt. Det är viktigt för användarens mentala hälsa. Dessutom har inte mycket förändrats, vilket inte ställer frustrerande krav på användaren. Windows 8 såg inte alls ut som Windows 7, vilket var frustrerande. Detta stämmer! Däremot kan man inte säga att en modern Macbook är mindre kraschbenägen än t.ex. en modern Surface – idag hittar du Windows t.ex. i atomubåtar och i kärnkraftverk.

2. Ekosystem i världsklass

En Mac och en Iphone samspelar bra, men det råder inga som helst tvivel om att både Google och Microsoft har kommit längre än Apple i arbetet med att fusionera sina plattformar, men Apple är fortfarande världsklass med en hedrande tredje plats.

3. Färre val gör dig lyckligare

Få modeller ger få val, vilket ger mindre beslutsångest. Man skriver att Apple har sju datorer i produktion – fyra bärbara och tre stationära. Microsoft har sin Surface Pro i lite olika utföranden, en Surface Book och en Surface Studio, och det är väldigt tydligt vilken produkt som vänder sig till vilken användare. Om färre val gör dig lyckligare, blir man då ännu lyckligare av ännu färre val? Då vinner Microsoft över Apple, men här jämför man sig med Lenovo, HP eller Dell, som alla har ett större produktutbud.

4. Du slipper virus

Det du inte vet, mår du inte dåligt av – när säkerhet verkligen är ett krav, hittar man nästan alltid Windows eller Linux.

5. Du får grymma program på köpet

När man jämför mjukvaruutbudet på Windows Phone med IOS så vinner Apple. Jämför man Windows 10 med Mac OS så vinner Windows 10. Utbudet av kvalitativ mjukvara som antingen ingår i Windows-licensen eller finns som open source för Windows, är oslagbart. Men om färre val gör dig lyckligare, så är det Windows Phone och Mac OS som tar hem priset.

6. Du får vad du betalar för

“Vill du ha en dator som baseras på den senaste tekniken och har en elegant design är Apples datorer ett utmärkt val. Men visst, om det viktiga är en billig dator som klarar surfande och Facebook finns det bättre alternativ.” En Mac är inte speciellt prisvärd eller up to date, och ofta blir de tiotusentalskroners Facebook-maskiner.

7. Det bara fungerar 

Allt fungerar out of the box, men det kan vara svårt att byta ut komponenter på egen hand. Detta är inte unikt för Apple. Jag kan t.ex. inte byta batteri på min Surface Pro, men självklart levereras en märkesdator fullt installerad, utan bloatware. Det gäller naturligtvis även Microsoft.

8. Skärmarna är fantastiska

Det råder inga tvivel om att Microsoft är stråt vassare här, men skärmarna är bra! De har dessutom touch, stöd för penna och Surface Dial.

9. Fri telefonsupport

Du kan inte ringa Microsoft hur som helst när du vill ha support, du får nöja dig med att ta det i text om det ska vara gratis. Här vinner Apple, något som du förmodligen betalar för när du köper adaptrar till överpris – there is no such thing as a free lunch.

10. Touch Bar är en innovation

Det är verkligen mer innovativt att dra och rita direkt på skärmen, men visst, detta är en innovation. Inte alla modeller har någon touch bar, dock.

11. Du kommer att bli nöjd

Om du köper en produkt som är dyr, så kommer du intala dig att du är nöjd, av psykologiska skäl. Så du kommer troligen bli nöjd, av helt fel orsak.

Min slutsats är att vi inte har att göra med “11 klockrena argument”, men väl “10 argument”.

Två nya SID-låtar

Jag har slängt ihop två nya SID-låtar som kan avnjutas på din Commodore 64.

Den ena (the_roger_boogie.sid) är ett resultat från ett demo-jam på jobbet tillsammans med Klas Dahlén, Roger Johansson och Erik Sandberg. Den är egenkomponerad och använder en samtida playerrutin (SID 8580). Förhandsgranskning finns på YouTube.

Den andra, som är en cover på låten I Touch Myself av Divinyls, slände jag ihop igår kväll. Den körs på en rutin som är anpassad till den gamla brödburken (SID 6582).

Ladda gärna hem filerna här!

Ghostbusters (2016)

Paul Feig lämnade nästan garantier på att rebooten av Ghostbusters skulle vara dålig. En kass trailer, en hip hop-remix av soundtracket, rasstereotyper, könsstereotyper och en provokativ damage control. Under resans gång lyckades Reddit publicera filmens synopsis och regissör Paul Feig lät hälsa att den så kallade “nördkulturen” innehåller några av planetens minst sympatiska människor.

Det sista vill jag kommentera, eftersom nördkulturen är något som ligger mig varmt om hjärtat. Jag är inte någon nörd, ens i ordets nya, positiva bemärkelse. Visst har jag fastnat lite i gamla Commodore-maskiner och Linda och Valentin-böckerna, men det jag gillar med nördkulturen är de riktiga nördarna. Och jag känner tillräckligt många för att kunna säga att man får leta på andra platser om man verkligen vill hitta några av planetens minst sympatiska människor.

Tvärt emot det intryck som trailern gav, så fungerade faktiskt många skämt. Det havererade lite när karaktären Kevin anställdes mot Abbys vilja, för att både Erin och Jillian hade mindre professionella motiv att vilja anställa honom. Den situationen hade kanske varit ännu värre om spökligan vore män som anställde en kvinna.

Trots att filmen hade högre budget än originalet, var specialeffekterna märkbart sämre. Personkemin mellan spökjägarna fungerade sisådär, men var och en var de jättebra. Regin var undermålig, vilket är det absolut bästa man kan förvänta sig av Feig.

En av de viktigaste orsakerna till att den nya Ghostbusters-filmen inte behöll samma spökliga som vi såg på bio 1984, är naturligtvis Harold Ramis bortgång. Men vi fick faktiskt se resten av gänget, Bill Murray, Ernie Hudson och Dan Aykroyd, skymta förbi. Förmodligen under tvång, med tanke på filmens rykte. Jag klickade på 6 av 10 på IMDb, och bidrog därmed till att (i skrivande stund) höja filmens snitt.

Uppdatering 2017-08-10: Mr. Plinkett’s Ghostbusters (2016) Review

Min första Cordova-app

Denna bloggpost är ett resultat av mitt första försök att skapa en plattformsoberoende app med Visual Studio 2015 och Cordova, som pratar med ett Web API.

När man väljer att skapa en Cordova-app i Visual Studio, får man med lite kod som man kanske inte vill ha med när man testar lite själv. Jag valde att rensa innehållet i den div vars klass heter “app”, helt tömma CSS-filen från innehåll, och rensa upp allt utom “pause” och “resume” från index.js.

Därefter installerade jag jQuery och jQuery Mobile. Här finns det två saker att tänka på. För det första passar inte nödvändigtvis den senaste jQuery Mobile ihop med den senaste jQuery. Efter en googling kunde jag konstatera att version 1.4.5 av jQuery Mobile fungerar med version 2.1.4 av jQuery, så dessa installerade jag.

Install-Package jquery -version 2.1.4
Install-Package jquery.mobile -version 1.4.5

Det andra att ha i åtanke är att script-filerna installeras i mapparna Scripts respektive Content. Men i en Cordova-app ska dessa ligga under www/scripts respektive www/css, så man måste manuellt flytta dem dit, genom att dra och släppa i Solution Explorer. Sen är det bara att inkludera i head-sektionen på index.html.

<script type="text/javascript" src="scripts/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="scripts/jquery.mobile-1.4.5.min.js"></script>

Inuti min div (“app”) placerar jag två bilder, “firstScreen” och “secondScreen”, där jag låter den första innehålla ett enkelt formulär och den andra vara dold.

<div id="firstScreen">
    <form target="http://localhost:64924/api/Values" method="get">
        <input type="text" id="p1" name="p1" />
        <br />
        <input type="text" id="p2" name="p2" />
        <br />
        <input type="button" onclick="submitForm();" />
    </form>
</div>
<div id="secondScreen" style="display: none;">
    Hello!
</div>

Koden för att skicka innehållet i formuläret till servern, antar att jag har ett enkelt Web API igång. Om det gick bra, presenterar jag svaret på den nya sidan och visar den. Om det inte gick bra, skriver jag fail i en textbox.

function submitForm() {
    var x = { p1: $("#p1").val(), p2: $("#p2").val() };

    $.post('http://localhost:64924/api/Values/', x, { headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' } })
    .success(function(data, status) {
        $("#firstScreen").hide();
        $("#secondScreen").text(data);
        $("#secondScreen").show();
    })
    .error(function(data, status) {
        $("#p1").val("Fail!");
    });
}

Cordova-appen pekar ut en ASP.NET Web API-applikation, som är väldigt lik exempelapplikationen som man får om man väljer att skapa en sådan i Visual Studio 2015. Jag pekar på den exempelcontroller som följde med, Values. Eftersom jag gör en http-post förväntar jag mig att metoden Post ska svara. Argumentet som jag tar emot, har två properties vars namn stämmer överens med datat i formuläret: p1 och p2. Funktionen gör just inget annat än att skicka tillbaka strängen “From server!” till Cordova-appen.

public string Post([FromBody]Testmeddelande value)
{
    return "From server!";
}

Därmed har jag en enkel plattformsoberoende app som kan samla in och skicka data, samt ta emot och presentera svaret.

Föreläsning om Commodore 64

Tisdagen den 27 september kl. 18:00 bjuder ABF i Örebro på en föreläsning om Commodore 64, i ABF:s lokaler på Fredsgatan 18 i Örebro.

Commodore 64 är fortfarande världens mest sålda hemdator, och trots att det gått 34 år sedan den introducerades på marknaden, släpps fortfarande nya spel till systemet, som fortfarande imponerar när det gäller grafik och ljud. Commodore 64 slog inte bara konkurrenterna Sinclair, Texas Instruments och Atari på fingrarna under 80-talet, utan lyckades överleva dem alla. Vad var det som gjorde att just Commodore 64 engagerade så många användare, programmerare, grafiker och musiker? Vad kunde datorn som inga andra system klarade av? Och vad är det som fortfarande lockar med just Commodore 64?

Föreläsare är Anders Hesselbom som har varit hemdatoranvändare sedan 1982 och idag är en inbiten programmerare och Commodore-entusiast.
I denna föreläsning berättar han varför just Commodore 64 sticker ut i jämförelse med andra system.

Hörselslinga finns.
Fika finns till försäljning

Facebook-event finns här. Föreläsningen är gratis och öppen för allmänheten. Välkommen!

Captured (Lars Hård)

An attempt to cover the C64 classic Captured soundtrack by Lars Hård.

Om du vill höra mer musik, mitt album från 2004 (tillsammans med Tommy Deile) finns på nätet här: Single Point of Failure – This time we are both

Mina C64-covers finns här: http://www.remix64.com/act/anders-hesselbom/

Dessutom, om du vill lyssna på mitt sommarprat i podcasten Kvack, om bl.a. min musik, så finns den här: http://kvackyou.se/2016/07/kvacksnack-sommar-2016-anders-hesselbom/

Hur kan vi utnyttja evolutionen?

Tack vare den ofrånkomliga utveckling som följer från förändring över tid, med selektion, och tack vare att vem som helst idag har tillgång till starka datorer, kan vi tämja evolutionen till att göra lite vad vi vill. Låt säga att jag t.ex. vill skapa ett korsord från en lista av ord. Antingen sätter jag mig ner och flätar orden manuellt, vilket kan vara nog så svårt. Eller så använder jag min PC för att skapa en algoritm som beskriver hur orden ska flätas ihop, vilket inte heller är speciellt enkelt.

Fördelen med evolutionära algoritmer är att jag bara behöver veta vad jag vill åstadkomma – jag behöver inte tänka på hur något görs. Om det är ett korsord som ska byggas, så skulle jag kunna tänka mig att mitt indata är t.ex. 20 – de ord som ska flätas ihop till ett korsord. Om jag kan definiera vad ett bra korsord är, så kan jag göra ett urval. Och kan jag göra ett urval, så kan jag låta slumpen göra jobbet. Jag behöver även ha två regler: en regel som säger att t.ex. ordet ASKA inte får korsas med ordet PILBÅGE, och en regel som säger att om ordet ASKA ska korsas t.ex. med ordet MATROS, så måste det ske på någon av de gemensamma bokstäverna (vilket är S eller A).

En tänkt initiering av korsordet skulle kunna vara att skapa 15 giltiga korsord genom att låta slumpen avgöra om ett ord ska vara vågrätt eller lodrätt, och sedan placera ut ordet på en tänkt matris, på en slumpvis utvald plats. Om ordet inte kan placeras på den plats som tilldelas, så slumpar vi fram en ny plats, så att reglerna upprätthålls. Detta upprepas för varje ord till dess att alla ord ligger på en giltig plats, vilket innebär att vi har ett giltigt korsord, om än förmodligen ett väldigt spretigt sådant.

Dessa 15 korsord kan vi betrakta som en lista av föräldrar. Jag brukar jobba med två generationer – en föräldrageneration och en barngeneration. Och det är från någon av dessa 15 korsord som det perfekta korsordet ska komma.

Nästa steg blir att låta varje korsord få 3 barn. Ett barn i detta fall är en kopia av ett korsord, med en slumpmässig förändring. Man kan låta slumpen avgöra om man ska positionera om ett ord, två ord eller tre ord. Man kan låta slumpen avgöra om något eller alla av dessa ord ska förvandlas från vågrätt till lodrätt, eller tvärt om. Vi som bygger evolutionära algoritmer har lånat en biologisk term för detta skeende, nämligen mutation. Barnen, 45 stycken, lagras i listan som representerar barngenerationen.

Varje barn poängsätts efter hur väl det är anpassat till sin miljö (där miljö egentligen är mina kriterier). En liten area ger högre poäng än en stor area, antal intersektioner mellan ord ger poäng, en mer rektangulär form ger högre poäng än en mer långsmal form, och så vidare. När alla 45 barnkorsord är poängsatta, sparar jag de bästa 15 i föräldragenerationen, tömmer barngenerationen, och upprepar processen.

Över tid kommer kvalitén (alltså likheten med mina kriterier) att förbättras, men om tillräckligt lång tid får passera så upphör förbättringen. Man kan tänka sig ett tröskelvärde som säger att om inte något korsord har förbättrats på, säg, 10 000 generationer, så är vi nöjda med vårt korsord – det korsord som har högst poäng.

Och därmed har jag skapat ett korsord utan att själv vara förmögen att varken placera ut orden på egen hand eller beskriva den algoritm som skulle göra detta. Allt samman bygger på att nästan var och varannan person idag, i sin ficka, förvaltar något som för 20 år sedan skulle betraktas som en superdator.

Pengar är ingen motivator

Arbetslösheten i Sverige har ökat stadigt sedan början av 70-talet, då den var 2%. Idag får vi räkna med att staten kostar pengar, att kommunerna kostar pengar, och att varje medborgare dessutom måste försörja 1/10 av en medmänniskas utgifter. Mycket få arbetslösa blir motiverade av betald utbildning och löfte om anställning – de som finner detta attraktivt återfinns bland den redan arbetande skaran.

Till en viss grad kan man lösa problem med statens finanser genom att höja skatten. T.ex. anser rikspolischef Dan Eliasson att vi har för få poliser, vilket rimligtvis är ett problem som kan lösas med skattehöjningar, om inte omprioriteringar.

Jag är själv anhängare av hypotesen att skatt kan vara ett styrmedel, vilket innebär att högre beskattning ger lägre konsumtion. I Sverige praktiseras detta på bensin, tobak och alkohol, men jag vet att idén inte är helt okontroversiell. Det finns dem som anser att hög skatt odiskutabelt leder till ökade inkomster för stat eller kommun. Rimligtvis anser alla att det finns en gräns, om inte annat när man passerar 100% inkomstskatt, och måste betala mer än man tjänar. Men de som kritiserar denna idé anser att man i alla tillstånd under 100% kan öka statens intäkter genom att höja skatten. Hur det än ligger till med denna sak, så är vi tvungna att förhålla oss – pengar är inte alltid en motivatör.

Som invånare i Mellansverige kan jag konstatera att en arbetssökande “hen” här, har anmält till diskrimineringsombudsmannen (DO) att hen kallats för hon. Jag försvarar hens rätt att bli kränkt till döden, men om en kränkning ska anmälas till DO, har jag svårt att se vilket jobb som är lämpligt för hen. Det ligger i sakens natur att en anställning följer till att göra saker man kanske inte alltid vill göra, och att man utsätter sig för saker man inte alltid vill utsätta sig för. Även jag själv kan ibland sitta och skriva kod som visualiserar affärslogik medan jag drömmer om att bygga ett actionspel där rymdskepp jagas av laserkanoner. Och jag tänker inte låta mig övertalas att det finns någon hen i hela världen som har haft en mindre komplicerad uppväxt än vad jag själv har haft – jag råkar bara ha en omodern könsidentitet.

Aftonbladet: Kallade “hen” för “hon” – anmäls för diskriminering

Lathund XAML: Reflektera förändringar vid data binding

En enkel databindning (alltså databindning av en post) åstadkommer man i WPF genom att tilldela ett objekt till DataContext för containern av kontrollerna som ska bindas. Här har jag tilldelat ett namn till Grid-elementet som ligger på huvudfönstret från början, och placerat en TextBox däri som jag binder till propertyn FirstName.

<Grid Name="theGrid">
   <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="283,103,0,0"
   TextWrapping="Wrap" VerticalAlignment="Top" Width="120"
   Text="{Binding FirstName}" />
</Grid>

Givet att programmet har tillgång till klassen Employee (förra exemplet) och att fönstret har en medlemsvariabeln (emp) av den typen, så kan vi i t.ex. Initialized-eventet göra tilldelningen till DataContext.

this.emp = new Employee() { FirstName = "Sven" };
this.theGrid.DataContext = this.emp;

Om vi under resans gång försöker läsa av propertyn FirstName, så kommer eventuella ändringar som användaren gjort i det bundna textfältet att ha reflekterats tillbaka till propertyn. Om vi är intresserade av att validera inmatat data behöver vi kunna registrera valideringsregler från programmet på kontrollens container. I mitt lilla exempelprojekt heter root-namnrymden WpfApplication1.

<Grid Name="theGrid" xmlns:val="clr-namespace:WpfApplication1">

Klassen som sköter valideringen måste ärva från klassen ValidationRule. Notera att jag kallar valideringsklassen för NameValidationRule.

class NameValidationRule : System.Windows.Controls.ValidationRule
{
   public int MinLength { get; set; }
   public string ErrorMessage { get; set; }

   public override ValidationResult Validate(object value, CultureInfo cultureInfo)
   {
      var s = (value as string == null ? "" : value as string).Trim();
      if (s.Length < this.MinLength)
         return new ValidationResult(false, this.ErrorMessage);
      return new ValidationResult(true, null);
   }
}

Därefter använder jag den XML-namnrymd jag tidigare registrerade (val) när jag registrerar klassen NameValidationRule.

<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="283,103,0,0"
   TextWrapping="Wrap" VerticalAlignment="Top" Width="120">
   <Binding Path="FirstName">
      <Binding.ValidationRules>
         <val:NameValidationRule MinLength="2" ErrorMessage="Fel!" />
      </Binding.ValidationRules>
   </Binding>
</TextBox>

Slutligen, om jag vill använda kod för att detektera att inmatningen inte validerar så finns det flera metoder. Den enklaste är att använda kontrollens funktion GetBindingExpression som ger ett objekt som helt enkelt har en property som heter HasError.

var binding = textBox.GetBindingExpression(TextBox.TextProperty);
if (binding.HasError)
   return;

Detta kan göras t.ex. när användaren klickar OK.

Grovhet

För många står oregelbundenhet i motsats till regelbundenhet, men i den matematiska världen står regelbundenhet i motsats till grovhet. Tänk dig att du ska mäta omkretsen på denna figur, en kochkurva:

koch1

Ju finare passare du använder för att mäta omkretsen, desto längre är omkretsen.

passare

En grov inställning på passaren kommer att ge mätvärden vars summa är mycket lägre, vilket innebär att den grova inställningen på mätinstrumentet ger ett resultat som beskriver en mindre grov figur.

koch2

En finare inställning på passaren kommer att ge mätvärden vars summa är mycket högre, vilket innebär att den fina inställningen på mätinstrumentet ger ett resultat som beskriver en grövre figur.

koch3

Denna egenskap gäller inte bara för kochkurvan utan även för en kustlinje eller en bergssiluett. Se gärna Benoît Mandelbrots föreläsning på TED. Mandelbrot är en fransk matematiker som givit namn åt mandelbrotfraktalen.

Stora tal

Det finns ett mycket roligt klipp med karaktären Ali G där han ställer sig frågan om en dator någonsin kan räkna ut ett väldigt stort godtyckligt tal. Han får svaret att alla räkneövningar han kan nämna, kan räknas ut av en modern dator. Din miniräknare kommer förmodligen slå i taket när talen blir för stora, men en vanlig PC med Windows kan ge dig precis vilket svar som helst. Det krävs lite trixande under skalet för att få detta att fungera.

Heltal representeras normalt av en bit-struktur, alltså ett antal ettor och nollor. Ett 32-bitars heltal är ett heltal som beskrivs av 32 bitar (4 bytes). Bitrepresentationen är liknar binärrepresentationen av ett tal, vilket innebär att både bitrepresentationen av talet 8 och binärrepresentationen av talet 8 är 1000. Ju större tal man vill beskriva, desto fler bitar behöver man ha, och förr eller senare slår man i taket.

Men det finns en struktur i Windows som heter BigInteger som inte har någon begränsning när det kommer till heltalsrepresentationer och heltalsberäkningar. Det beror på att talen internt lagras som en teckensekvens istället för som ett bitmönster, där varje tecken i sin tur representeras av ett begränsat bitmönster. Då blir det hela en fråga om hur många tecken som får plats i minnet, vilket är väldigt många. För att få se vad BigInteger-strukturen kan göra, kan man skriva in en enkel kod i PowerShell som dubblerar ett tal ett antal gånger. Om jag börjar med talet 1 och dubblar det så får jag 2. Dubblar jag det så får jag 4, 8, 16, 32, 64, 128, 256, och så vidare. Ganska snart blir talet väldigt stort. Redan efter blott 100 dubbleringar landar man på talet 2 535 301 200 456 458 802 993 406 410 752 vars binära representation skulle bli väldigt stor. Men i en BigInteger-struktur är detta bara att betrakta som 31 tecken som avkodas till värden i turordning när beräkningar ska göras.

Så utrustade med BigInteger-strukturen kan vi se vad som händer när vi dubblerar ett tal 500 gånger. För att göra detta, skriv:

$x = New-Object System.Numerics.BigInteger 1; for ($i = 0; $i -le 500; $i++) { $x *= 2; Write-Output $x }

PowerShell levererar svaret på ett ögonblick. Talet 1 dubblat 500 gånger ger oss talet 6 546 781 215 792 283 740 026 379 393 655 198 304 433 284 092 086 129 578 966 582 736 192 267 592 809 349 109 766 540 184 651 808 314 301 773 368 255 120 142 018 434 513 091 770 786 106 657 055 178 752, vilket är ett så stort tal att det nästan är omöjligt att läsa ut och förstå. För att underlätta kan man använda scientific notation. Istället för att skriva ut föregående tal i sin fulla längd, kan man skriva:

6,55 * 10150

Eller:

6,55E150

Båda varianterna säger oss att talet börjar på 6 och innehåller 150 siffror till därefter, varav de första nästkommande är 55 (avrundat). Det totala antalet siffror i talet är alltså antalet siffror till vänster om decimalavgränsaren plus talet till höger om E. 151 stycken.

Så hur står sig en etta dubblerad femhundra gånger mot andra stora tal?

Vårt observerbara Universum uppskattas innehålla 1,7 * 1011 (eller 1,7E11) galaxer. Uppskattningsvis finns 1024 (1E24) stjärnor i Universum.

Båda dessa tal är alltså relativt små i jämförelse med den etta vi dubblade femhundra gånger. Hur är det med antalet atomer i vårt observerbara Universum? Faktum är att även det är ett relativt litet tal i detta sammanhang, nämligen 4 * 1080 (4E80), alltså en fyra följt av åttio nollor. 400 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000.

Så låt oss dubbla vår etta femtusen gånger. Även det räknas fram kvickt av PowerShell. Svaret är 282 493 406 427 885 207 367 041 933 403 229 466 733 779 235 036 908 223 362 737 617 171 423 633 968 541 502 511 617 825 263 342 305 274 671 206 416 862 732 165 528 407 676 139 958 676 671 942 371 453 279 846 862 103 555 703 730 798 023 755 999 290 263 414 138 746 996 425 262 647 505 106 222 430 745 688 071 901 801 071 909 721 466 836 906 811 151 133 473 603 131 174 810 929 399 280 998 101 699 398 944 715 801 811 235 142 753 236 456 432 868 426 363 041 983 113 354 252 997 303 564 408 348 123 661 878 478 353 722 682 766 588 036 480 451 677 385 451 192 294 010 288 486 562 150 551 258 990 678 187 626 397 933 471 267 212 659 382 047 684 908 251 671 777 313 746 267 962 574 481 960 017 676 147 336 443 608 528 865 821 788 061 578 040 438 881 156 396 976 534 679 536 477 744 559 804 314 840 614 495 141 020 847 691 737 745 193 471 783 611 637 455 592 871 506 037 036 173 282 712 025 702 605 093 453 646 018 500 436 656 036 503 814 680 490 899 726 366 531 275 975 724 397 022 092 725 970 923 899 174 562 238 279 814 456 008 771 885 761 907 917 633 109 135 250 592 173 833 771 549 657 868 899 882 724 833 177 350 653 880 665 122 207 329 113 965 244 413 668 948 439 622 163 744 809 859 006 963 982 753 480 759 651 997 582 823 759 605 435 167 770 997 150 230 598 943 486 938 482 234 140 460 796 206 757 230 465 587 420 581 985 312 889 685 791 023 660 711 466 304 041 608 315 840 180 083 623 903 760 913 411 030 936 698 892 365 463 484 655 371 978 555 215 241 419 051 756 637 532 976 736 697 930 030 949 995 728 239 530 882 866 713 856 024 688 223 531 470 672 787 115 758 429 874 008 695 136 417 331 917 435 528 118 587 185 775 028 585 687 114 094 178 329 752 966 233 231 383 772 407 625 995 111 380 343 784 339 467 510 448 938 064 950 157 595 661 802 643 159 880 254 674 421 388 754 566 879 844 560 548 121 596 469 573 480 869 786 916 240 396 682 202 067 625 013 440 093 219 782 321 400 568 004 201 960 905 928 079 577 408 670 605 238 675 195 724 104 384 560 742 962 264 328 294 373 028 338 181 834 383 818 752.

I scientific notation skrivs detta tal 2,82 * 101505 eller 2,82E1505. Med tanke på att vi ännu inte närmat oss någon bortre gräns, så kan man lugnt konstatera att den som äger en vanlig PC förvaltar en svindlande räkningskapacitet.

Gosbust 0.9.2

Version 0.9.2 av Gosbust finns nu att ladda hem. Tillåt mig presentera några exempel på vad aktuell version kan göra.

Det stora tillskottet handlar om stödet för arrayer. Kommandot ARRY tar ett namn (A-Z, A#-Z#, A$-Z$ eller A?-Z?) samt önskat antal element. 5 ger fem element med index 0-4.

ARRY A 5

Detta kolliderar inte med en eventuell enskild buffer som heter A. R$ och R$[3] lagras i olika minnesstrukturer. För att nå individuella element används hakparenteser. Detta skapar ett slumptal i arrayen A’s första element:

RAND A[0]

Om jag läser av element 0 borde jag se ett heltal, vilket som helst men troligen inte 0.

<<A[0]

Element 1 borde däremot fortfarande ha värdet 0, eftersom ingen tilldelning gjorts än.

<<A[1]

Om jag skulle önska ha ett slumptal i samtliga element i arrayen A, kan jag ersätta indexet med tre punkter:

RAND A[...]

Nu kan jag läsa av vilket element som helst (0-4) och få ett värde. Om jag skulle önska se samtliga element så kan jag skriva följande:

<<A[...]

Modulus kan inte appliceras på samtliga element i en array, så skulle jag önska att alla slumptal ska ligga mellan 0 och 9 kan jag skriva följande:

0>>I Mod: A[I]%10>>A[I] I++ I<10>>R? GOTO R? Mod

Om du använvänder konsollen så skulle bubbelsortering av 10 tal mellan 0 och 99 skulle se ut så här:

10 ARRY A 10 RAND A[...]
20 0>>I Mod: A[I]%100>>A[I] I++ I<10>>R? GOTO R? Mod
30 <<"Ej sorterat:" <<A[...]
40 0>>I 0>>J
50 Repeat: A[I]>A[J]>>S? GOSB S? Swap
60 I++ I>9>>I? GOSB I? NextOuter GOTO 1 Repeat
70 ShowResult: <<"Sorterat:" <<A[...]
80 QUIT 0
90 (Swap A[I]<>A[J] )
100 (NextOuter 0>>I J++ J>9>>J? GOTO J? ShowResult )

Notera att QUIT 0 lika gärna kan ersättas med RTRN. Om callstacken är tom har dessa två kommandon samma betydelse. Men om man skulle vilja avsluta med en felkod så kan QUIT n användas.

(Om du läser in en fil istället för att använda konsollen behövs inte radnumren.)

Mycket nöje!