rand.Next()

From Esolang
Jump to navigation Jump to search

rand.Next() is an esoteric programming language created by User:Checkmate in 2011. It uses the .NET Pseudo random number generator to generate brainfuck code. The only valid characters are the ASCII space, \n and \r. To maintain some compatibility between Operating Systems, there is no difference between LF and CR. Basically, the interpreter creates an instance of System.Random using the sum of the length of the code and the current day of year as a seed. Therefore, every rand.Next() program will behave differently every day. Then, for every (not empty) line of source code, another instance of System.Random called "rand" is created, using the sum of the current line's length and a random number from the previously created generator between 0 and 99. Finally, a single BF character is created based on rand.Next() modulo 8:

rand
.next()
% 8
BF
char
0 >
1 <
2 +
3 -
4 .
5 ,
6 [
7 ]

Then that character is interpreted. rand.Next() is Turing complete because it can (theoretically) translate into any BF program.[citation needed] When writing programs, note that they will translate to entirely different BF every day.

Implementation

The source code of a very simple interpreter in C# is below:

    // Program.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    
    namespace rand.Next
    {
        class Program
        {     
            static void Main(string[] args)
            {
                if (args.Length != 1 && args.Length != 0)
                {
                    Console.WriteLine("Invalid number of command-line arguments!");
                    Console.ReadKey();
                    Environment.Exit(0);
                }
    
                string code;
                if (args.Length == 1)
                    code = File.ReadAllText(args[0]);
                else
                {
                    code = Console.ReadLine();
                    code = code.Replace('!', '\n');
                }
    
                var sb = new StringBuilder();
    
                var rand = new Random(code.Length + DateTime.Today.DayOfYear);
    
                if (!code.All(c => c == ' ' || c == '\n' || c == '\r'))
                {
                    Console.WriteLine("Illegal characters found!");
                    Console.ReadKey();
                    Environment.Exit(0);
                }
    
                foreach (string s in code.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    var r = new Random(s.Length + rand.Next(0, 100));
                    switch (r.Next() % 8)
                    {
                        case 0:
                            sb.Append('>');
                            break;
    
                        case 1:
                            sb.Append('<');
                            break;
    
                        case 2:
                            sb.Append('+');
                            break;
    
                        case 3:
                            sb.Append('-');
                            break;
    
                        case 4:
                            sb.Append('.');
                            break;
    
                        case 5:
                            sb.Append(',');
                            break;
    
                        case 6:
                            sb.Append('[');
                            break;
    
                        case 7:
                            sb.Append(']');
                            break;
    
                        default:
                            break;
                    }
                }
    
                if (args.Length == 0)
                {
                    Console.WriteLine(sb.ToString());
                }
    
                var interpreter = new Interpreter(sb.ToString(), ReadByteKey, PrintByte);
                interpreter.Run();
            }
    
            static byte ReadByteKey()
            {
                char ch = Console.ReadKey().KeyChar;
                return Encoding.ASCII.GetBytes(ch.ToString())[0];
            }
    
            static void PrintByte(byte input)
            {
                Console.Write(Encoding.ASCII.GetChars(new byte[] { input }));
            }
        }
    }
    
    // Interpreter.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace rand.Next
    {
        class Interpreter
        {
            static Dictionary<char, Action> Dict = new Dictionary<char, Action>();
            static byte[] Arr = new byte[30000];
            static int Ptr = 0;
            static Stack<int> CallStack = new Stack<int>();
            static int IP = 0;
    
            static Func<byte> Input;
            static Action<byte> Output;
            static string Code;
    
            public Interpreter(string code, Func<byte> input, Action<byte> output)
            {
                Input = input;
                Output = output;
                Code = code;
    
    
                Dict.Add('+', () => { Arr[Ptr]++; });
                Dict.Add('-', () => { Arr[Ptr]--; });
                Dict.Add('>', () => { if (Ptr == 29999) Ptr = 0; else Ptr++; });
                Dict.Add('<', () => { if (Ptr == 0) Ptr = 29999; else Ptr--; });
                Dict.Add('.', () => { Output(Arr[Ptr]); });
                Dict.Add(',', () => { Arr[Ptr] = Input(); });
                Dict.Add('[', () => { CallStack.Push(IP); });
                Dict.Add(']', () =>
                    {
                        var temp = CallStack.Pop() - 1;
                        IP = Arr[Ptr] != 0
                            ? temp
                            : IP;
                    });
            }
    
            public void Run()
            {
                try
                {
                    while (IP < Code.Length)
                    {
                        char instruction = Code[IP];
                        Action action;
                        if (Dict.TryGetValue(instruction, out action))
                        {
                            action();
                        }
    
                        ++IP;
                    }
                }
                catch (Exception ex)
                {
                    if (ex.Message == "Stack empty.")
                    {
                        Console.WriteLine("Unmatched square brackets.");
                    }
                    else
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
            }
        }
    }