diff options
author | Camil Staps | 2016-06-11 18:49:57 +0200 |
---|---|---|
committer | Camil Staps | 2016-06-11 18:49:57 +0200 |
commit | e44fa4401d4de7d8af090f9bc825ab0846f57058 (patch) | |
tree | d0de248c0b469de46f22d0a3725ebfe980c9e3fd | |
parent | CleanSmurf (diff) |
Nederlands; codestijl
-rw-r--r-- | analyse.tex | 18 | ||||
-rw-r--r-- | explanation-inner.tex | 87 | ||||
-rw-r--r-- | explanation-outer.tex | 47 | ||||
-rw-r--r-- | explanation.tex | 17 | ||||
-rw-r--r-- | introexmp.tex | 1 |
5 files changed, 123 insertions, 47 deletions
diff --git a/analyse.tex b/analyse.tex index 0021771..fa21cf6 100644 --- a/analyse.tex +++ b/analyse.tex @@ -4,10 +4,16 @@ Omdat de transities van onze natuurlijke semantiek input meenemen, kunnen we alleen een afleidingsboom maken voor een programma \emph{met} een bepaalde -input. Het is dus niet triviaal mogelijk een afleidingsboom te maken voor willekeurige -input. In deze sectie willen we laten zien hoe het toch mogelijk is een bewijs -te leveren over een programma met een willekeurige input string, door gebruik te maken -van inductie naar de lengte van de input string. We hadden hiervoor initieel een programma op het internet \cite{esolang:prog} gevonden welke een string zou moeten omdraaien. Echter werkte dit programma niet naar behoren. Het werkte namelijk niet voor strings met lengte een. Daarom hebben we zelf een programma geschreven voor het omdraaien van een string. Dit programma ziet er als volgt uit: +input. Het is dus niet triviaal mogelijk een afleidingsboom te maken voor +willekeurige input. In deze sectie willen we laten zien hoe het toch mogelijk +is een bewijs te leveren over een programma met een willekeurige input string, +door gebruik te maken van inductie naar de lengte van de input string. We +hadden hiervoor initieel een programma op de Esolang wiki gevonden dat een +string zou omdraaien~\cite{esolang:prog}. Dit programma werkte echter niet naar +behoren: het werkte niet voor strings met lengte $1$. Daarom hebben we zelf een +programma geschreven voor het omdraaien van een string. Dit programma ziet er +als volgt uit: + \begin{smurf} \footnotesize i "input" p @@ -27,8 +33,8 @@ i "input" p g x \end{smurf} -Het bovenstaande programma is in het format van smurf maar echter is dit programma niet zo leesbaar. -Daarom hebben we getracht het programma iets leesbaardere te maken: +Het bovenstaande programma is correcte Smurfsyntax en hierdoor niet erg +leesbaar. We hebben daarom getracht het programma iets leesbaarder te maken: \input{reverse2} diff --git a/explanation-inner.tex b/explanation-inner.tex index 10a5ab3..cb81c46 100644 --- a/explanation-inner.tex +++ b/explanation-inner.tex @@ -1,4 +1,23 @@ -Het binnenste programma draait strings van lengte n + 1 om. Hiervoor krijgt het twee "argumenten" geprepend mee. Het eerste argument is een string in zijn oorspronkelijke volgorde, die elke recursieve aanroep \'{e}\'{e}n karakter kleiner wordt. Het tweede argument is een string die initi\"{e}el de lege string is, maar bij elke recursieve aanroep \'{e}\'{e}n karakter groter wordt en de omgekeerde string voorstelt. De reden dat dit programma alleen voor strings van lengte n + 1 werkt is als volgt: het testen van waarden kost zoals we eerder hadden gezien een programma-aanroep. Wij hebben ervoor gekozen om eerst de string te verkleinen en daarna te kijken of we de lege string hebben bereikt (de hele string is omgedraaid) om te bepalen of we dit programma nog eens moeten uitvoeren met nieuwe argumenten. Als je zou willen bepalen of je inputstring leeg was voordat je deze verkleint zou je 2 recursieve programma's nodig hebben die elkaar telkens aanroepen: \'{e}\'{e}n die als eerste test of de input leeg en daarop gebaseerd \'{o}f het andere programma aanroept \'{o}f output geeft en eindigt en een ander programma dat de string verkleint en dan het eerste programma aanroept om weer de waarde te testen. Het leek ons dus beter om aan het einde te testen of we door moeten gaan en het geval van de lege string op te vangen in het buitenste programma. +% vim: set spelllang=nl: +\subsubsection{Het recursieve binnenste programma} +Het binnenste programma draait strings van lengte n + 1 om. Hiervoor krijgt het +twee "argumenten" geprepend mee. Het eerste argument is een string in zijn +oorspronkelijke volgorde, die elke recursieve aanroep \'{e}\'{e}n karakter +kleiner wordt. Het tweede argument is een string die initi\"{e}el de lege +string is, maar bij elke recursieve aanroep \'{e}\'{e}n karakter groter wordt +en de omgekeerde string voorstelt. De reden dat dit programma alleen voor +strings van lengte n + 1 werkt is als volgt: het testen van waarden kost zoals +we eerder hadden gezien een programma-aanroep. Wij hebben ervoor gekozen om +eerst de string te verkleinen en daarna te kijken of we de lege string hebben +bereikt (de hele string is omgedraaid) om te bepalen of we dit programma nog +eens moeten uitvoeren met nieuwe argumenten. Als je zou willen bepalen of je +inputstring leeg was voordat je deze verkleint zou je 2 recursieve programma's +nodig hebben die elkaar telkens aanroepen: \'{e}\'{e}n die als eerste test of +de input leeg en daarop gebaseerd \'{o}f het andere programma aanroept \'{o}f +output geeft en eindigt en een ander programma dat de string verkleint en dan +het eerste programma aanroept om weer de waarde te testen. Het leek ons dus +beter om aan het einde te testen of we door moeten gaan en het geval van de +lege string op te vangen in het buitenste programma. Het recursieve omdraaiprogramma ziet er zo uit: @@ -75,26 +94,46 @@ g x }} \end{center} -\textbf{(1)} De argumenten worden er de eerste keer opgezet door het buitenste programma. Merk op dat het y-argument in het buitenste programma \texttt{"\textbackslash"\textbackslash""} is, wat de gequotifyde versie is van \texttt{""}, oftewel de lege string. Het x-argument is dan de niet-lege input. -\textbf{(2)} Hierna wordt de een string van de rest van het programma (vanaf (3)) op de stack gezet. Dit zorgt ervoor dat recursie mogelijk is. -\textbf{(3)} Het programma en de argumenten worden in variabelen opgeslagen. "program" voor het programma, "grow" voor het rechterargument, "shrink" voor het linkerargument. -\textbf{(4)} De waarde van "shrink" wordt opgehaald en vervangen door zijn eerste karakter. Daarna wordt "grow" opgehaald en het eerste karakter van "shrink" wordt eraan geappend. Het resultaat hiervan wordt weggeschreven naar "grow". -\textbf{(5)} Nu wordt de waarde van "shrink" nog eens opgehaald, vervangen door zijn tail en weer teruggeschreven naar "shrink". Nu is het eerste karakter van shrink dus naar achter "grow" verplaatst. -\textbf{(6)} De nieuwe waarde van "shrink" wordt nu al vast op de stack gezet, voor dezelfde reden dat dit in het buitenste programma met "input" gebeurde. Wanneer we hem later nodig hebben hebben we niet de garantie dat de variabelenaam niet overschreven is, dus we zetten hem er nu al op. -\textbf{(7)} De nieuwe waarde van "grow" wordt opgehaald en gequotifyed. Ook appenden we "o" eraan. Zo vormt het een programmastring die die waarde zou outputten wanneer uitgevoerd. Dit moeten we doen als "shrink" leeg is geworden. Merk op dat het programma dat moet worden uitgevoerd wanneer de string leeg is geworden in tegenstelling tot in het buitenste programma hier v\'{o}\'{o}r het andere programma wordt aangemaakt. Dit doen we omdat we hier een waarde van een variabele gebruiken en we niet weten of de variabele straks overschreven wordt. We bouwen deze programmastring dus al vast, maar laten hem nog gewoon op de stack staan. -\textbf{(8)} "shrink" en "grow" worden opgehaald en gequotifyed. Ook "program" wordt opgehaald en gequotifyed. Dit alles appenden we aan elkaar. Nu wordt "program" nog eens opgehaald, niet gequotifyed en aan de eerdere sting geappend. Nu is deze hele string gelijk aan het hele programma, maar met de nieuwe waarden van "grow" en "shrink" als argumenten. -\textbf{(9)} Nu komt het deel waar we de waarde van shrink testen om te kiezen of we output moeten geven, of nog een recursiestap moeten uitvoeren. De waarde van "shrink" wordt opgehaald en gebruikt als variabelenaam om het programma dat we in (8) hadden gebouwd naar weg te schrijven. Vanaf dit punt kunnen we geen van onze variabelen meer gebruiken, omdat de waarde van "shrink" toevallig gelijk zou kunnen zijn geweest aan de naam van een van onze variabelen. -\textbf{(10)} Nu schrijven we het programma dat we in (7) hadden gebouwd en nog op de stack stond weg naar de variabele met naam de lege string. -\textbf{(11)} Nu halen we de waarde op van de variabele met als naam de waarde van "shrink" die we in (6) al op de stack hadden gezet. Als "shrink" leeg was vinden we het programma uit (7). Anders vinden we het programma uit (8). We voeren het gevonden programma uit. - - - - - - - - - - - - +\textbf{(1)} De argumenten worden er de eerste keer opgezet door het buitenste +programma. Merk op dat het y-argument in het buitenste programma +\texttt{"\textbackslash"\textbackslash""} is, wat de gequotifyde versie is van +\texttt{""}, oftewel de lege string. Het x-argument is dan de niet-lege input. +\textbf{(2)} Hierna wordt de een string van de rest van het programma (vanaf +(3)) op de stack gezet. Dit zorgt ervoor dat recursie mogelijk is. +\textbf{(3)} Het programma en de argumenten worden in variabelen opgeslagen. +"program" voor het programma, "grow" voor het rechterargument, "shrink" voor +het linkerargument. \textbf{(4)} De waarde van "shrink" wordt opgehaald en +vervangen door zijn eerste karakter. Daarna wordt "grow" opgehaald en het +eerste karakter van "shrink" wordt eraan geappend. Het resultaat hiervan wordt +weggeschreven naar "grow". \textbf{(5)} Nu wordt de waarde van "shrink" nog +eens opgehaald, vervangen door zijn tail en weer teruggeschreven naar "shrink". +Nu is het eerste karakter van shrink dus naar achter "grow" verplaatst. +\textbf{(6)} De nieuwe waarde van "shrink" wordt nu al vast op de stack gezet, +voor dezelfde reden dat dit in het buitenste programma met "input" gebeurde. +Wanneer we hem later nodig hebben hebben we niet de garantie dat de +variabelenaam niet overschreven is, dus we zetten hem er nu al op. +\textbf{(7)} De nieuwe waarde van "grow" wordt opgehaald en gequotifyed. Ook +appenden we "o" eraan. Zo vormt het een programmastring die die waarde zou +outputten wanneer uitgevoerd. Dit moeten we doen als "shrink" leeg is geworden. +Merk op dat het programma dat moet worden uitgevoerd wanneer de string leeg is +geworden in tegenstelling tot in het buitenste programma hier v\'{o}\'{o}r het +andere programma wordt aangemaakt. Dit doen we omdat we hier een waarde van een +variabele gebruiken en we niet weten of de variabele straks overschreven wordt. +We bouwen deze programmastring dus al vast, maar laten hem nog gewoon op de +stack staan. \textbf{(8)} "shrink" en "grow" worden opgehaald en gequotifyed. +Ook "program" wordt opgehaald en gequotifyed. Dit alles appenden we aan elkaar. +Nu wordt "program" nog eens opgehaald, niet gequotifyed en aan de eerdere sting +geappend. Nu is deze hele string gelijk aan het hele programma, maar met de +nieuwe waarden van "grow" en "shrink" als argumenten. \textbf{(9)} Nu komt het +deel waar we de waarde van shrink testen om te kiezen of we output moeten +geven, of nog een recursiestap moeten uitvoeren. De waarde van "shrink" wordt +opgehaald en gebruikt als variabelenaam om het programma dat we in (8) hadden +gebouwd naar weg te schrijven. Vanaf dit punt kunnen we geen van onze +variabelen meer gebruiken, omdat de waarde van "shrink" toevallig gelijk zou +kunnen zijn geweest aan de naam van een van onze variabelen. \textbf{(10)} Nu +schrijven we het programma dat we in (7) hadden gebouwd en nog op de stack +stond weg naar de variabele met naam de lege string. \textbf{(11)} Nu halen we +de waarde op van de variabele met als naam de waarde van "shrink" die we in (6) +al op de stack hadden gezet. Als "shrink" leeg was vinden we het programma uit +(7). Anders vinden we het programma uit (8). We voeren het gevonden programma +uit. diff --git a/explanation-outer.tex b/explanation-outer.tex index a538a90..691a2ea 100644 --- a/explanation-outer.tex +++ b/explanation-outer.tex @@ -1,7 +1,22 @@ -Het buitenste programma test of we te maken hebben met de lege string als inputstring. Als dit het geval is geef je de lege string als output. Anders ga je het recursieve subprogramma in, dat alleen voor strings van lengte n + 1 gedefini\"{e}erd is. -Omdat Smurf geen statement heeft om waarden te testen moeten we hier op een slimme manier omgaan met het feit dat waarden ook als variabelenaam kunnen worden gebruikt. Eerst schrijven we het recursieve programma dat we moeten aanroepen als de inputstring niet leeg is naar de variabele met als naam de inputstring zelf. Hierna schrijven we het programma dat moet worden uitgevoerd als de string leeg is (het outputten van de lege string) naar de variabele met als naam de lege string. Als de inputstring leeg is overschrijven we daar dus het recursieve programma dat we eerst aan die variabele hadden toegewezen. Als laatste voeren we het programma uit dat op de variabele met naam de inputstring staat. +% vim: set spelllang=nl: +\subsubsection{Het buitenste programma} +Het buitenste programma controleert of we te maken hebben met de lege string +als inputstring. Als dit het geval is geeft het de lege string als output. +Anders wordt het recursieve subprogramma gebruikt, dat alleen voor strings van +lengtes groter dan nul gedefini\"{e}erd is. -Dit buitenste programma ziet er als volgt uit: +Omdat Smurf geen conditionals kent, moeten we hier op een slimme manier omgaan +met het feit dat waarden ook als variabelenaam kunnen worden gebruikt. Dit is +vergelijkbaar met \autoref{exmp:headortail}. Eerst schrijven we het recursieve +programma dat we moeten aanroepen als de inputstring niet leeg is naar de +variabele met als naam de inputstring zelf. Hierna schrijven we het programma +dat moet worden uitgevoerd als de string leeg is (het outputten van de lege +string) naar de variabele met als naam de lege string. Als de inputstring leeg +is overschrijven we daar dus het recursieve programma dat we eerst aan die +variabele hadden toegewezen. Als laatste voeren we het programma uit dat op de +variabele met naam de inputstring staat. + +Het buitenste programma ziet er als volgt uit: \begin{center} \makebox{ \parbox{35mm}{ @@ -33,7 +48,25 @@ g x }} \end{center} -\textbf{(1)} Allereerst wordt de inputstring op de stack gezet en naar de variabele met naam "input" geschreven. De stack is nu weer leeg. \textbf{(2)} Nu zetten we de inputwaarde weer op de stack voor later gebruik. De reden hiervoor volgt straks. -\textbf{(3)} Hierna halen we deze inputwaarde voor de tweede keer op, quotifyen we hem en prependen we het tot de subprogramma-string. Dit kun je zien als het doorgeven van een argument. De reden dat we de input quotifyen is dat dit ervoor zorgt dat alle karakters in de input behouden blijven (ook die met speciale betekenis zoals "\textbackslash{}") wanneer het subprogramma wordt uitgevoerd. Het subprogramma staat zelf al gequotifyed hier. -Op dit moment staat het grote programma met de input eraan geprepend op de stack, met als element eronder de inputwaarde die we zo nodig hebben. \textbf{(4)} Nu halen we opnieuw de waarde van de input op uit de variabele waarnaar we het eerst hadden weggeschreven en gebruiken we dit als een variabelenaam om het subprogramma naar weg te schrijven. Merk op dat we onze opslag van de inputstring verliezen als die toevallig de waarde "input" had, omdat we die variabele dan overschrijven. Dit is waarom we deze waarde van tevoren een keer extra op de stack hebben gezet. Zo kunnen we hem bij (6) nog gebruiken. \textbf{(5)} Nu zetten we het gequotifyde programma "output de lege string" op het register met naam de lege string. Ongequotifyed ziet het er zo uit: \texttt{""o} -\textbf{(6)} Als laatste halen we het programma op van de variabele met als naam de inputstring die we in (2) op de stack hadden gezet en voeren we dit programma uit.
\ No newline at end of file +\textbf{(1)} Allereerst wordt de inputstring op de stack gezet en naar de +variabele met naam "input" geschreven. De stack is nu weer leeg. \textbf{(2)} +Nu zetten we de inputwaarde weer op de stack voor later gebruik. De reden +hiervoor volgt straks. \textbf{(3)} Hierna halen we deze inputwaarde voor de +tweede keer op, quotifyen we hem en voegen we het toe aan het begin van de +subprogramma-string. Dit kun je zien als het doorgeven van een argument. De +reden dat we de input quotifyen is dat dit ervoor zorgt dat alle karakters in +de input behouden blijven (ook die met speciale betekenis zoals +"\textbackslash{}") wanneer het subprogramma wordt uitgevoerd. Het subprogramma +staat zelf al gequotifyed hier. Op dit moment staat het grote programma met de +input eraan voorgevoegd op de stack, met als element eronder de inputwaarde die +we zo nodig hebben. \textbf{(4)} Nu halen we opnieuw de waarde van de input op +uit de variabele waarnaar we het eerst hadden weggeschreven en gebruiken we dit +als een variabelenaam om het subprogramma naar weg te schrijven. Merk op dat we +onze opslag van de inputstring verliezen als die toevallig de waarde "input" +had, omdat we die variabele dan overschrijven. Dit is waarom we deze waarde van +tevoren een keer extra op de stack hebben gezet. Zo kunnen we hem bij (6) nog +gebruiken. \textbf{(5)} Nu zetten we het gequotifyde programma "output de lege +string" op het register met naam de lege string. Ongequotifyed ziet het er zo +uit: \texttt{""o} \textbf{(6)} Als laatste halen we het programma op van de +variabele met als naam de inputstring die we in (2) op de stack hadden gezet en +voeren we dit programma uit. diff --git a/explanation.tex b/explanation.tex index ffbf8ae..4771ffa 100644 --- a/explanation.tex +++ b/explanation.tex @@ -2,16 +2,13 @@ \subsection{Het omdraaiprogramma uitgelegd} \label{sec:uitleg programma} -Om uit te leggen hoe dit programma precies functioneert zullen we een programma bekijken dat identiek is aan het programma dat we analyseren, op de namen van de gebruikte variabelen na. (In de analyse zijn de namen kleiner gemaakt, zodat de bewijsbomen minder breed zouden worden) -"program" correspondeert met "u", -"grow" met "v" en -"shrink" met "w". -Ook zullen we het programma opdelen in twee aparte programma's die elk apart bekeken kan worden zodat het geheel beter te begrijpen is. -\medskip +Om uit te leggen hoe dit programma precies functioneert, zullen we een +programma bekijken dat er identiek aan is, op de namen van de gebruikte +variabelen na. In de analyse zijn de namen kleiner gemaakt, zodat de +bewijsbomen minder breed zouden worden. De variabele \texttt{program} +correspondeert met \texttt{u}, \texttt{grow} met \texttt{v} en \texttt{shrink} +met \texttt{w}. We zullen het programma opdelen in twee aparte programma's die +elk apart bekeken kunnen worden zodat het geheel beter te begrijpen is. -\subsubsection{Het buitenste programma} \input{explanation-outer} - -\subsubsection{Het recursieve binnenste programma} \input{explanation-inner} - diff --git a/introexmp.tex b/introexmp.tex index 2ebe1eb..90ed119 100644 --- a/introexmp.tex +++ b/introexmp.tex @@ -27,6 +27,7 @@ aangeven hoe conditionele executie kan worden behaald in Smurf. %\end{exmp} \begin{exmp} + \label{exmp:headortail} Dit programma laat de gebruiker kiezen welke functie er wordt uitgevoerd: \begin{smurf} "h""head"p "t""tail"p \\ |