I boken "The Pragmatic Programmer" (om du inte har läst den, sluta läsa den här artikeln och gör det nu!) står det att vi varje år bör lära oss ett nytt programmeringsspråk.
Även om vissa kanske hävdar att det är för mycket ansträngning, kan vi alla hålla med om att det kan vara en bra idé. Att välja ett nytt språk att lära sig är inte så lätt. Vi vill ju inte ägna vår tid åt något som vi kanske aldrig kommer att använda i praktiken, eller hur? Men ibland kanske vi ska göra ett undantag och lära oss något bara för att det är roligt? Jag skulle vilja presentera Brainfuck-språket för dig. Det är ett språk som du kan lära dig på ett par minuter, så det finns inget problem med att investera för mycket av din tid i onödan. Jag kan också lova att om du löser alla problem med Brainfuck kommer din hjärna att stimuleras (alla f*cks är bara en bonus ;)). Låt oss komma igång!Enligt Wikipedia:
Brainfuck är en esoteriskt programmeringsspråk skapades 1993 av Urban Müller. Språket består av endast åtta enkla kommandon och en instruktionspekare. Även om det är helt Turing-komplett är det inte avsett för praktisk användning, utan för att utmana och roa programmerare.
Språköversikt
Föreställ dig ett oändligt långt band som består av celler, var och en initialiserad till 0. Det finns också en rörlig datapekare som initialt pekar på den första cellen. Det finns också två strömmar av bytes för in- och utmatning. Instruktionerna utförs sekventiellt, en efter en. Maskinen stannar efter att den sista instruktionen har utförts.
Kommando
Vad gör den?
>
flytta datapekaren till nästa cell till höger
<
flytta datapekaren till nästa cell till vänster
+
Öka värdet för aktuell cell
–
minska värdet för aktuell cell
.
mata ut byten i en cell som pekas ut för tillfället i ASCII kod
,
läsa en byte från stdin och lagra dess värde i den aktuella cellen
[
om den aktuella cellen är 0 hoppar du till den matchande ]
]
hoppa till den matchande [
Alla andra tecken än ><+-.,[] ignoreras.
Låt oss titta på ett enkelt exempel:
,+.
Den kommer att tolkas på följande sätt:
läs en byte och lagra den i aktuell cell (cell0)
öka värdet för aktuell cell (cell0 = cell0 + 1)
skriva innehållet i aktuell cell till utdata
Som ett resultat kommer ett tecken att läsas från inmatningen och nästa tecken från ASCII-tabellen kommer att skrivas ut.
Tolkare / kompilator
Innan vi skriver några användbara (?) program i Brainfuck behöver vi en tolk eller en kompilator. AFAIK, det finns ingen officiell, men det är inte ett problem. Det finns dussintals inofficiella på Internet. Jag kan rekommendera dessa två:
"Hello World!" borde vara det första program som vi skriver när vi lär oss ett nytt språk. Men att skriva det i Brainfuck är lite svårare än i andra språk. Vi måste börja med något enklare... Låt oss skriva ett program som skriver ut en enda bokstav "H" på skärmen (så spännande :D):
Hur fungerar det här? Den ställer in värdet på aktuell cell till 72 (med 72 steg) och skriver ut det på skärmen med "." (H har kod 72 i ASCII). Nu vet du vad vi ska göra för att skriva ut "Hello World!" på skärmen, men innan dess ska vi göra en liten refaktorisering. Att skriva alla dessa '+' kräver för mycket skrivande och räknande. Vi kan göra det kortare genom att använda [ och ] för loopning. För att sätta värdet till 72 kan vi t.ex. göra en slinga som ökar värdet 7 gånger med 10. På så sätt får vi 70. Om vi lägger till 2 blir det 72. Det ser ut så här:
++++++++++ # ställ in cell0 till 10
[ # loop tills cell0 är 0
- # minska cell0
> # flytta datapekaren till höger (cell1)
+++++++ # öka cell1 med 7
# flytta datapekaren till höger (cell1)
++ # öka med 2
. # skriv ut resultatet
Jag har inkluderat kommentarer för att göra det tydligt hur allt fungerar. Samma program utan kommentarer:
++++++++++[->+++++++++.
Visst är det vackert? 🙂 🙂
Hej, världen!
Vi går tillbaka till vårt "Hello World!"-program. Vi kan sätta värdet på den första cellen till 72 (H) och skriva ut det, sätta värdet på den andra cellen till 101 (e) och skriva ut det, sätta värdet på den tredje cellen till 108 och skriva ut det och så vidare. Här är implementeringen av denna algoritm:
Ja, bara 1120 byte för att skriva ut "Hello World!" ... Men vi kan göra bättre! Istället för att använda en ny cell för varje tecken, låt oss använda bara en. För att skriva ut bokstaven "e" (101) kan vi återanvända värdet i cell0 (72). Vi kan öka det med ett 29 gånger (101 - 72). Och resultatet blir som följer:
Den är bara 106 bytes och den skriver ut en ny rad i slutet! Fantastiskt.
Vändning av en sträng
Nu är vi redo att skriva något mer utmanande. Låt oss skriva ett program som läser en rad från indata och skriver ut den i omvänd ordning. Det första problemet är att läsa tecken och stoppa vid det nya radtecknet. Kom ihåg att det inte finns någon bryta, om eller andra liknande uttalanden. Vi måste använda [ och ]. Låt oss börja med ett program som läser alla tecken från inmatningen och placerar dem i på varandra följande celler:
,[>,]
Det börjar med att läsa första tecknet och fortsätter till sista , operationens avkastning 0. Den kommer dock att loopa för evigt i implementationer som returnerar något annat än O för EOF (språket specificerar inte detta beteende). Så hur kan vi stanna på det nya linjetecknet? Här är tricket:
+[++++++++++>,----------]
Vi börjar med att cell0 sätts till 1 för att se till att vår loop körs minst en gång. I en loop ökar vi värdet på den aktuella cellen med 10, flyttar datapekaren till nästa cell, läser ett tecken och minskar dess värde med 10. På detta sätt, om det läses ett nytt radtecken (10 i ASCII), kommer programmet att stanna i nästa iteration, annars kommer dess värde att återställas genom att lägga till 10.
Efter detta steg kommer våra celler att se ut så här:
11 C1 C2 C3 0* 0 0
Cn är det n:te tecknet från inmatningen, och * är datapekarens aktuella position. Nu måste vi börja flytta datapekaren åt vänster och skriva ut alla celler tills vi når värde 11. Här är mitt sätt att ta itu med uppgiften:
Jag uppmuntrar dig att analysera det på egen hand :-).
Sammanfattning
När jag snubblade över Brainfuck, ett esoteriskt programmeringsspråk, avfärdade jag det först som inget annat än en gimmick eller ett skämt. Detta märkliga, och som många kanske hävdar, ett förbluffande svårt språk, verkade för mig som något som bara var avsett för underhållning. Men med tiden förändrades min uppfattning om Brainfuck ganska dramatiskt.
Brainfucks gåtfulla natur utmanar dig och får dig att vidga ditt perspektiv på programmeringsspråk. Detta esoteriska språk gör att du kan uppskatta skönheten och nödvändigheten i de högnivåspråk som vi är vana vid. Det sätter fokus på betydelsen av abstraktioner, korrekta namnkonventioner och en organiserad minneslayout inom programmeringsspråken. Detta är något som Brainfuck, med sin minimalistiska design bestående av bara åtta enkla kommandon, inte tillhandahåller.
Brainfuck är ett Turing-komplett språk som ytterligare understryker vikten av att ha en tydlig och sammanhängande källkod. Trots att det är erkänt som ett av de mest utmanande esoteriska språken att skriva program i, lyser det ironiskt nog som en nybörjares favorit för alla som vill skapa en egen Brainfuck-kompilator eller en Brainfuck-tolk. Anledningen är enkelheten i dess kommandouppsättning och det faktum att det inte kräver komplex parsning.
Att skapa ett Brainfuck-program är unikt på två sätt. För det första måste du anpassa dig till användningen av en enda minnespekare, vilket tvingar dig att tänka annorlunda om din källkod. För det andra har du "nollalternativet", vilket är möjligheten att återställa minnescellen till noll, en funktion som inte är vanlig i andra formella programmeringsspråk.
När det gäller inlärning finns det mer än vad som syns när det gäller Brainfuck. Med tillräckligt med tid och rätt inställning är det möjligt att skriva samma program på en mängd olika sätt med hjälp av olika Brainfuck-koder. Den sista halvan av den här resan handlar om att vara uppfinningsrik och hitta nya, kreativa sätt att använda de sex symbolerna.
Brainfuck-tolkarna är minimalistiska, men ger dig en djup förståelse för hur koden körs, vad programmet skriver ut och den underliggande mekaniken i ett Turing-komplett språk. I slutändan är Brainfuck inte bara ytterligare ett esoteriskt programmeringsspråk. Det är en helt ny dimension, ett nytt sätt att se på hur vi ser, förstår och skriver program.