Talk:2001: An Esolang Odyssey
Jump to navigation
Jump to search
Implementation
This is an implementation in Visual Basic. You can provide a program as input, or, if UseSpecifiedCode is set to true, you can run the code inside the string. Compiling code with UseSpecifiedCode is equivalent to (but not quite) compiling 2001: An Esolang Odyssey. I did try to implement command line arguments for this, but it has not been tested thoroughly and appears to not work the best.
Imports System Imports System.Collections.Generic Imports System.Text.RegularExpressions Imports System.Numerics Module _2001_AnEsolangOdyssey Dim Code As New List(Of String) Dim Left As New Stack(Of Integer) Dim Right As New Stack(Of Integer) ' ---[DIFFERENCES FROM SPECIFICATION]--- ' The original specification says the cells ' should be unbounded, but BigIntegers are ' really weird to deal with in Visual Basic. ' ' Therefore, I have used a 64-bit integer instead, ' which should fulfill most purposes. Dim Current As Long = 0 Dim MainDepth As Integer = 0 ' Set this to True if you want to insert the code ' in the interpreter source (in SpecifiedString), ' False if you want to get the program from console input. ' ' --[NOTES]-- ' * Console input programs need to have @End appended to them. ' "Stop, Dave." does not suffice since it can appear in the ' middle of a program. ' * Using True does not make this program a true compiler, ' but makes compiling this program equivalent to compiling ' 2001: An Esolang Odyssey code. You can therefore make ' actual 2001: An Esolang Odyssey executables (.exe). ' Because of this I have provided a way to use command-line ' arguments. Dim UseSpecifiedCode As Boolean = False ' Set this to True if you want to give the 2001AEO program ' access to command-line arguments. ' ' Command-line arguments are put to the left of ' the starting pointer position, with the ' rightmost character of the rightmost ' argument being the one directly to ' the left of the pointer. ' ' From left to right, the format is: ' * -2 (This provides a marker to allow the code to ' stop at the correct point when trying to find the ' first argument. Ascii codes should never be negative ' numbers, so this provides a valuable marker. ' * Any number of arguments ' * A list of ascii codes of the characters of the argument ' * -1 (Another marker to get to the beginning or end of an argument) ' ' A good way to get to the -2 marker is this code snippet: ' ----------------------------------------------------------- ' Hal? Hal! Hal! ' What are you doing, Dave? ' I'm afraid. I'm afraid, Dave. Dave, my mind is going. I can feel it. I can feel it. ' I've picked up a fault in the AE-35 unit. ' Hal? Hal! Hal! ' Dave, this conversation can serve no purpose anymore. Goodbye. ' I'm afraid. I'm afraid, Dave. Dave, my mind is going. I can feel it. I can feel it. ' ----------------------------------------------------------- ' That only works if you are to the right of it, but you can replace ' the 4th line in that snippet with ' "Well, he acts like he has genuine emotions." to go from the left instead. ' ' The marker/anchor cell idea is from a video by mitxela on YouTube. Dim UseCommandLineArgs As Boolean = False ' The specification says to throw an error if the program tries ' to input and hits EOF, but by setting this to false it will input -1 instead. Dim ThrowErrorOnNoInput As Boolean = True ' Insert your program here if UseSpecifiedCode is True. Dim SpecifiedString As String = "Good afternoon, gentlemen. I am a Hello World computer. I became operational at Foobar Lane on May 6th, 2020. I've picked up a fault in the AE-35 unit. I've picked up a fault in the AE-35 unit. Close the pod bay doors, HAL. Stop, Dave." Dim SpecifiedCode As List(Of String) = New List(Of String) (SpecifiedString.Split(New Char(){vbCr(0), vbLf(0)})) Sub Main(Args As String()) If Not UseSpecifiedCode Then While True Dim Line As String = Console.ReadLine() If Line.Equals("@End") Then Exit While End If Code.Add(Line) End While End If If UseSpecifiedCode Then Code = SpecifiedCode End If If Not Regex.IsMatch(Code(0), "Good afternoon\, gentlemen\. I am a .* computer\. I became operational at .* on .*\.") Then Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: Program did not begin with a proper greeting.") End If If Not Code(Code.Count - 1).Equals("Stop, Dave.") Then Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: Program did not end with ""Stop, Dave.""") End If Dim I = 0 While I < Code.Count If Code(I).Equals("What are you doing, Dave?") Then MainDepth += 1 ElseIf Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then MainDepth -= 1 End If I += 1 End While If UseCommandLineArgs Then Left.Push(-2) For J As Integer = 0 To Args.Length For K As Integer = 0 To Args(J).Length Left.Push(AscW(Args(J)(K))) Next Left.Push(-1) Next End If MainDepth = 0 I = 0 While I < Code.Count ' Where N is the number of times " Hal!" ' minus the quotes appears at the end of ' this instruction, HAL will increment his ' current cell by N. If Regex.IsMatch(Code(I), "Hal\?( Hal\!)+") Then Current = Current + (((Code(I).Length - 4) / 5)) ' Where N is the number of times "I can feel it" ' minus the quotes appears at the end ' of this instruction, HAL will decrement ' his current cell by N. ElseIf Regex.IsMatch(Code(I), "I'm afraid\. I'm afraid\, Dave\. Dave\, my mind is going\.( I can feel it\.)+") Then Current = Current - (((Code(I).Length - 53) / 15)) ' If HAL's current cell is zero, he will ' go to the matching loop end. This is a loop start. ElseIf Code(I).Equals("What are you doing, Dave?") Then If Current = 0 Then Dim Depth = 1 While Depth > 0 I = I + 1 If Code(I).Equals("What are you doing, Dave?") Then Depth = Depth + 1 End If If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then Depth = Depth - 1 End If If I >= Code.Count Then Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: Unmatched loops.") End If End While Else MainDepth = MainDepth + 1 End If ' If HAL's current cell is nonzero, ' he will go back to the matching ' loop start. This is a loop end. ElseIf Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then If Not Current = 0 Then Dim Depth = 1 While Depth > 0 I = I - 1 If Code(I).Equals("What are you doing, Dave?") Then Depth = Depth - 1 End If If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then Depth = Depth + 1 End If If I < 0 Then Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: Unmatched loops.") End If End While Else MainDepth = MainDepth - 1 End If ' HAL will break out of the innermost ' two loops he is in (or one or none if ' he isn't in at least two loops). ElseIf Code(I).Equals("This mission is too important for me to allow you to jeopardize it.") Then If MainDepth = 0 Then ElseIf MainDepth = 1 Then Dim Depth = 1 While Depth > 0 I = I + 1 If Code(I).Equals("What are you doing, Dave?") Then Depth = Depth + 1 End If If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then Depth = Depth - 1 End If End While Else Dim Depth = 2 While Depth > 0 I = I + 1 If Code(I).Equals("What are you doing, Dave?") Then Depth = Depth + 1 End If If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then Depth = Depth - 1 End If End While End If ' HAL will break out of all loops he is currently in. ElseIf Code(I).Equals("I know I've made some very poor decisions recently, " + "but I can give you my complete assurance that my wor" + "k will be back to normal.") Then Dim Depth = MainDepth While Depth > 0 I = I + 1 If Code(I).Equals("What are you doing, Dave?") Then Depth = Depth + 1 End If If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then Depth = Depth - 1 End If End While ' HAL will move his cell pointer one cell to the left. ElseIf Code(I).Equals("I've picked up a fault in the AE-35 unit.") Then If Left.Count = 0 Then Left.Push(CInt(0)) End If Right.Push(Current) Current = Left.Pop ' HAL will move his cell pointer one cell to the right. ElseIf Code(I).Equals("Well, he acts like he has genuine emotions.") Then If Right.Count = 0 Then Right.Push(CInt(0)) End If Left.Push(Current) Current = Right.Pop ' HAL will set his current cell to a user ' input character; no input and an error ' message will be displayed, and he will ' set his current cell to zero, but the ' program will not be terminated. ElseIf Code(I).Equals("Open the pod bay doors, HAL.") Then Current = Console.Read() If ThrowErrorOnNoInput AndAlso Current = -1 Then Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: EOF reached on input.") End If ' HAL will output his current cell as a character. ElseIf Code(I).Equals("Close the pod bay doors, HAL.") Then Dim OutputChar = ChrW(Current) Console.Write(OutputChar) ' To write a comment, type ' "Hal_Memory.EntryAdd: " ' (there must be a space at the end). ' This isn't actual code and doesn't mean ' anything, but it fits the AI context. ' You can of course very easily change this ' string to something else in this implementation ' but that would make it even less portable. ' ' -------------------------------------------- ' THIS IS NOT IN THE SPECIFICATION, ' AND DEGRADES PORTABILITY. ' -------------------------------------------- ElseIf Code(I).StartsWith("Hal_Memory.EntryAdd: ") Then Current = Current + 0 ' Whitespace only lines or blank lines ' also do nothing, allowing some nice formatting. ' -------------------------------------------- ' THIS IS NOT IN THE SPECIFICATION, ' AND DEGRADES PORTABILITY. ' -------------------------------------------- ElseIf Regex.IsMatch(Code(I), "\s*") Then Current = Current + 0 ' Multiline comments can be done with ' "[[" to start and "]]" to end. ' They must be on their own line. ' Usually multiline comment borders ' should not overlap loop borders, ' but there may be use cases for that. ' ' The main thing that will happen when ' overlapping a loop and a comment will ' be that the loop will start running the comment ' if it is valid code and the value is zero, ' and it will break out of the loop prematurely ' if the value is non-zero and skip the comment entirely. ' This can effectively be an if-else construct. ' ' Doing these kinds of things is extremely unstable, ' though, and for these reasons it is a bad idea to ' include lines containing only ' "What are you doing, Dave?" ' or ' "Dave, this conversation can serve no purpose anymore. Goodbye." ' (without quotes) ' ' If you really need those lines in your comment, ' differentiate them in some way like prepending them ' with some symbol. ' ' Break commands should be safe though. ' ' -------------------------------------------- ' THIS IS NOT IN THE SPECIFICATION, ' AND DEGRADES PORTABILITY. ' -------------------------------------------- ElseIf Code(I).Equals("[[") Then While Code(I).Equals("]]") I += 1 End While End If I = I + 1 End While End Sub End Module
BoundedBeans (talk) 19:22, 21 August 2022 (UTC)
- I've realized recently that the block of code that says
If UseCommandLineArgs
requires thatThen
be following it. I'm honestly surprised the program even runs at all. I've changed it in the code block above. BoundedBeans (talk) 01:47, 6 December 2022 (UTC)