Iterate

From Esolang
Jump to navigation Jump to search
Not to be confused with ITERATE.

Iterate is a Turing complete programming langugage invented by User:Aadenboy which only uses iterative loops.

Syntax

Loops

Loops are initialized with an asterisk (optionally with a number preceding it surrounded by parentheses), followed by the amount of times it loops, then the loop itself. There are only loops. Outside of a loop, its index is zero.

Code Definition
*#< ... > Loop # times. If it is zero or nothing, don't run. The visit count will still accumulate regardless of whether or not it had looped.
*∞< ... > Loop forever.
*< ... > Skip the code inside.
(#*)...< ... > A labeled loop for future reference. # must be a number. Different loops can share a single label if they are within separate scopes.
(*)...< ... > The main loop. This must enclose the entire program.

A visit is defined as every time the program encounters a loop or label, regardless of whether or not the body actually runs. Note the difference between loops and labels, as labels can be shared across loops, so long as a label only appears once within its scope.

Loop amounts

You are able to provide different loop amounts via referencing other loops, or by a constant. A loop many only use one amount.

Code Definition
Number That many times.
Infinity.
? File: Advances the cursor to and uses the first string of numbers to the right of the cursor, or to EOF with 0 if there is none.


CLI: Parses the user's input as a number. Negative and invalid inputs are zero. Floats are rounded down.

~? File: Parses the next bytes as a UTF-8 character, returning the codepoint. If it is invalid, it is equivalent to zero and all invalid bytes are skipped.


CLI: All the characters inputted are added to a buffer that is parsed like in the file case. Further invocations of ~? or %? use the buffer instead of another IO read until it is empty.

%? File: Returns the next byte.


CLI: All the characters inputted are added to a buffer that is parsed like in the file case. Further invocations of ~? or %? use the buffer instead of another IO read until it is empty.

n The current index of the parent loop. This equals zero for the main loop's parent.
n# The current index of label #. This equals zero if the label doesn't exist.
n^ The current index of the main loop.
~n How many loops are left until the parent loop's final loop. This equals zero for the main loop's parent.
~n# The above command, but with a label. This equals zero if the label doesn't exist.
~n^ The above command, but with the main loop.
= How many times the parent loop was visited. This is not the same as how many times a label was visited. This equals zero for the main loop's parent.
=# How many times a label was visited. This is not the same as how many times a certain loop was visited. This equals zero if the label doesn't exist.
=^ The above command, but with the main loop. Usually equal to one unless you explicitly reset it.

For the input values (?, ~?, and %?), behavior will vary for file/data stream input and CLI input.

Commands

These are placed in a loop.

Code Definition
! Immediately break out of the parent loop. Analogous to break.
!# Immediately break out of label # IF you are inside it. This is a no-op if otherwise.
!^ Stop execution.
& Skip to the end of the parent loop. Analogous to continue.
&# Skip to the end of label # IF you are inside it. This is a no-op if otherwise.
&^ Skip to the end of the main loop.
@ Output the current index of the parent loop as a number.
~@ Output the current index of the parent loop as a UTF-8 formatted character.
%@ Output the current index in byte form, mod 256.
$ Reset the visit count of the parent loop.
$# Reset the visit count of label #.
$^ Reset the visit count of the main loop.

Completeness

Iterate is Turing complete. See Iterate/Turing-completeness proof.

Unsolved question: Is Iterate Turing complete without the $# command?

Basic arithmetic

For a complete list of mathematical operations, see Iterate/Math.

A+B

(*)1<
  *?< (1*)<> > // increment L1
  *?< (1*)<> > // increment L1 again
  (2*)=1<      // output character
    *~n< &2 >  // skip to prevent early prints
    @
    !^         // end early to avoid printing 0 case
  >
  (3*)48<      // print 0 as its ASCII code (48)
    *~n< &3 >  // skip to prevent early prints
    ~@
  >
>

A-B

Note: Results lower than one will not output anything.

(*)1<
  *?< (1*)<> > // L1 = A
  *?<          // decrement L1 by one B times
    $2
    *=1<            // store L1-1 in L2
      *~n< (2*)<> > // ~n acts as L1-1
      !
    >
    $1
    *=2< (1*)<> >   // copy from L2 to L1
  >
  (3*)=1<      // output character
    *~n< &3 >  // skip to prevent early prints
    @
    !^         // end early to avoid printing 0 case
  >
  (4*)48<      // print 0 as its ASCII code (48)
    *~n< &4 >  // skip to prevent early prints
    ~@
  >
>

A*B

(*)1<
  *?< (1*)<> > // store A to L1
  *?< (2*)<> > // store B to L2
  *=1<
    *=2<
      (3*)<>   // visited A*B times as an intrinsic property of nested loops
    >
  >
  (4*)=3<      // output character
    *~n< &4 >  // skip to prevent early prints
    @
    !^         // end early to avoid printing 0 case
  >
  (5*)48<      // print 0 as its ASCII code (48)
    *~n< &5 >  // skip to prevent early prints
    ~@
  >
>

A%B

(*)1<
  *?< (1*)<> >        // L1 = A
  *?< (2*)<> (4*)<> > // L2 = B, L4 = B
  (6*)=1<             // increment L3 to equal L1
    (3*)<>            // L3 = L3 + 1
    $5
    *=4< (5*)<> >     // L5 = L4
    $4
    *=5<           
      *~n< (4*)<> >   // L4 = L5 - 1
      !
    >
    *=4< &6 >         // if L4 == 0 (or when modulus returns 0)...
    $3                // L3 = 0
    *=2< (4*)<> >     // L4 = L2 (reset count)
  >
  (7*)=3<             // print result
    *~n< &7 >         // skip to prevent early prints
    @
    !^                // end early to avoid printing 0 case
  >
  (8*)48<             // print 0 as its ASCII code (48)
    *~n< &8 >         // skip to prevent early prints
    ~@
  >
>

A/B

The same algorithm can be used to calculate floored division.

(*)1<
  *?< (1*)<> >
  *?< (2*)<> (4*)<> >
  (6*)=1<         // a%b algorithm
    (3*)<>
    $5
    *=4< (5*)<> >
    $4
    *=5<           
      *~n< (4*)<> >
      !
    >
    *=4< &6 >
    $3
    *=2< (4*)<> >
    (7*)<>        // count how many times L3 resets for the quotient
  >
  (10*)1<
    (8*)=7<       // print quotient
      *~n< &8 >
      @
      !10
    >
    (9*)48<
      *~n< &9 >
      ~@
    >
  >
  (11*)82<        // "R"
    *~n< &11 >
    ~@
  >
  (12*)=3<        // print remainder
    *~n< &12 >
    @
    !^
  >
  (13*)48<
    *~n< &13 >
    ~@
  >
>

Conditionals

While this code checks if A == B, you can trivially modify it to check for A < B, A > B, and any combination or negation of those cases.

(*)1<
  *?< (1*)<> > // L1 = A
  *?< (2*)<> > // L2 = B
               // L7 will hold if A == B: 1 = true, 0 = false
               // we'll continuously decrement A and B until either reaches 0
               // if either reaches 0 first before the other, they're not equal
               // otherwise they are equal
  (5*)∞<
    (6*)1<        // we check FIRST for the edge case where either A or B starts as 0
      *=1<
        *=2< !6 > // case 1: neither A nor B are 0 -> continue
        !5        // case 2: B reached 0 first     -> A > B
      >
      *=2<
        *=1< !6 > // case 1: neither A nor B are 0 -> continue
        !5        // case 3: A reached 0 first     -> A < B
      >
      (7*)<>      // case 4: both reached 0 at the same time -> A == B
      !5
    >
    $3
    $4
    *=1< (3*)<> >        // L3 = L1
    *=2< (4*)<> >        // L4 = L2
    $1
    $2
    *=3< *~n< (1*)<> > ! > // L1 = L3 - 1
    *=4< *~n< (2*)<> > ! > // L2 = L4 - 1
  >
  *=7< @ !^ > // print 1 if true
  (8*)48<     // print 0 if false
    *~n< &8 >
    ~@
  >
>

Arbitrary memory

Arbitrary memory can be implemented with a single label using arbitrary memory emulation.

Example programs

Hello, world!

(*)1<
  *1< (1*)72< *~n< &1 > ~@ ! > >      // H
  *1< (1*)101< *~n< &1 > ~@ ! > >     // e
  *1< (1*)108< *~n< &1 > ~@ ~@        // ll
    *1< (2*)111< *~n< &2 > ~@         // o
      *1< (3*)44< *~n< &3 > ~@ ! > >  // ,
      *1< (3*)32< *~n< &3 > ~@ ! > >  //  
      *1< (3*)119< *~n< &3 > ~@ ! > > // w
    ~@ ! > >                          // o
    *1< (2*)114< *~n< &2 > ~@ ! > >   // r
  ~@ ! > >                            // l
  *1< (1*)100< *~n< &1 > ~@ ! > >     // d
  *1< (1*)33< *~n< &1 > ~@ ! > >      // !
>

Cat program

(*)∞<
  (2*)1<
    (1*)?<      // get input
      *~n< &1 > // skip all actions until the index equals the character
      ~@        // output the character
      &2        // skip past the break
    >
    !^ // if input is 0, assume no more input and stop execution
  >
>

Truth-machine

(*)1<
  *?<         // if input were to be 0, this wouldn't run
    *∞<       // loop forever
      *1< @ > // loop for index of 1 printed
    >
  >
  (1*)48<     // printing 0 as its ASCII code (48)
    *~n< &1 > // skip to prevent early prints
    ~@
  >
>

Looping counter

(*)∞<
  *n<
    (1*)42<
      *~n< &1 >
      ~@
    >
  >
  (1*)10<
    *~n< &1 >
    ~@
  >
>

Triangular numbers

(*)∞<
  *n<
    *~n<
      (1*)<>
    >
    !
  >
  (4*)1<
    (2*)=1<
      *~n< &2 >
      @
      !4
    >
    (3*)48<
      *~n< &3 >
      ~@
    >
  >
  (5*)10<
    *~n< &5 >
    ~@
  >
>

FizzBuzz

(*)∞<
  $1 $2 $3 $4 $5 $6 $7 $8 $9 $12
  *n^< (1*)<> >
  *3< (4*)<> (5*)<> > // mod 3
  *5< (6*)<> (7*)<> > // mod 5
  *=1< // calculates mod 3 and mod 5 at the same time
    (2*)<>
    (3*)<>
    $8 $9
    *=5< (8*)<> >
    *=7< (9*)<> >
    $5 $7
    *=8< *~n< (5*)<> > ! >
    *=9< *~n< (7*)<> > ! >
    *1< (10*)1<
      *=5< &10 >
      $2
      *=4< (5*)<> >
    > >
    *1< (10*)1<
      *=7< &10 >
      $3
      *=6< (7*)<> >
    > >
  >
  *1< (11*)1< // if mod 3 == 0
    *=2< !11 >
    *1< (12*)70< *~n< &12> ~@ > >     // F
    *1< (12*)105< *~n< &12> ~@ > >    // i
    *1< (12*)122< *~n< &12> ~@ ~@ > > // zz
  > >
  *1< (11*)1< // if mod 5 == 0
    *=3< !11 >
    *1< (12*)66< *~n< &12> ~@ > >     // B
    *1< (12*)117< *~n< &12> ~@ > >    // u
    *1< (12*)122< *~n< &12> ~@ ~@ > > // zz
  > >
  
  (13*)n< // print number if neither condition was met
    *=12< !13 >
    *~n< &13 >
    @
  >
  (14*)10< // newline
    *~n< &14 >
    ~@
  >
>

Further reading

Interpreter