### Nickolas's blog

By Nickolas, 8 years ago, translation, , Roco is a very simple language. On one hand, it's esoteric, so everything you need to know about it fits in two pages. On the other hand, it's powerful enough to enable writing rather complicated programs in it without racking one's brains over each elementary operation (like in Brainfuck). Being able to refer variables using names (numerical, but names nevertheless) is already a gift to the programmer :-)

#### 188A - Hexagonal Numbers

As usual, the first problem tests the competitor's understanding of basic arithmetic operations. The solution is very similar to the example.

iin 
mul   2
dec 
mul   
iout 
ac


Starting with the second one, the problems need learning the main feature of the language — the coroutines. A coroutine is a named piece of code executed in an endless loop. Something in between a procedure (without input parameters and variables, but with a name used for calling it) and a loop (without loop counter or break conditions, but with a chance to break it at any moment), coroutines allow to implement both these concepts.

#### 188B - A + Reverse B

The key element of this problem is reversing a number (we knew how to add the second number to it ever since the example). There are two ways to do this: either read the number as a sequence of characters and accumulate its reverse simultaneously, or read the number as, well, a number and calculate its reverse using math. I used the second approach, so I needed a single loop-like coroutine which stopped when the number being reversed turned zero.

/* coroutine to reverse a number  into  */
co reverse {
eq   0
if 
ac

/* find current number modulo 10 */
mod   10
/* add it to reversed number */
mul   10
/* and divide current number */
div   10
}

iin 
iin 
ca reverse
iout 
ac


#### 188C - LCM

In other languages the easiest way to get LCM of two numbers is recursive. The specifics of Roco is that one can't write a recursion with a single coroutine calling itself — after the second call of the coroutine its execution continues from the place where it stopped last time. So it was easier to rewrite the standard algorithm as a loop.

/*  - a
 - b
*/
co gcd {
eq   0
if 
ac
set  
set  
mod   
}

iin 
iin 
set  
set  
ca gcd
/* now   is gcd */
div   
mul   
iout 
ac


#### 188D - Asterisks

Ok, let's move on to a more complicated task: here we need a nested loop, the outer one running through the lines and the inner one — through the asterisks in the line. The inner loop will be called several times (from each iteration of the outer one), so here one could meet the mentioned feature of the coroutines for the first time.

/*  - * quantity
 - current line
 - current * in line
*/

co one_row {
lt   
if 
ac
cout 42
inc 
}

co print_all {
lt   
if 
ac
set  1
ca one_row
cout 10
inc 
}

iin 
set  1
ca print_all
ac


#### 188E - HQ9+

This time one can't solve this problem in one line using regular expressions, since this language has none. So one has to do it in an old-fashioned way, reading characters one-by-one and checking them for equality with each of the required ones. The code is rather long — there are three characters to compare each one to, and the answer has to be printed char-by-char, but overall there is nothing complex here.

/*  - YES or NO
 - current char
*/

co one_char {
cin 

eq   10
if 
ac

/* H */
eq   72
or   
/* Q */
eq   81
or   
/* 9 */
eq   57
or   
}

co say_yes {
cout 89
cout 69
cout 83
cout 10
ac
}

co say_no {
cout 78
cout 79
cout 10
ac
}

set  0
ca one_char
/* output the result stored in  */
if 
ca say_yes
dec 
if 
ca say_no
ac


Three last problems are almost real programming :-) They use the fact that in Roco variables are referenced not by names but by their indices in the heap, and the index can in turn be the contents of a variable. One can do more interesting things with arrays, but the programs become longer and more error-prone.

#### 188F - Binary Notation

The bad thing about the binary notation is that the digits are calculated right-to-left but have to be printed left-to-right. This can be done without arrays (reverse the number in binary using the math trick from 188B - A + Reverse B and then print its digits in the same order as they are calculated), but I used an array solution which first calculates the digits and writes them into an array and then goes through the array from the end to the start and prints the digits.

/*  - current number
 - index of last digit calculated
.. - service cells
..[] - the actual digits of the number
*/

co calculate_digits {
/* stop when the number is 0 */
eq   0
if 
ac

/* get next digit - put it to its location directly */
mod []  2
/* update the number and its notation length */
div   2
inc 
}

co output_digits {
/* stop when the next digit printed will be outside of the number */
eq   9
if 
ac

/* output the digit at  */
iout []
dec 
}

iin 
set  10
ca calculate_digits
dec 
ca output_digits
ac


#### 188G - Array Sorting

Unlike Befunge, in Roco the memory size limit is technical, not conceptual, so one could coed counting sort as well as comparison-based sort. Here is a code for the former one.

/* .. - the counts of numbers
 - quantity of numbers
 - current number
 - current index
*/

iin 

set  1
co init {
eq   101
if 
ac
set [] 0
inc 
}
ca init

set  0
eq   
if 
ac
iin 
inc []
inc 
}

set  1
co print_sorted {
eq   101
if 
ac
set  1
co print_one_number {
gt   []
if 
ac
iout 
cout 32
inc 
}
/* due to coroutine property (!), call only for positive quantity of numbers*/
gt  [] 0
if 
ca print_one_number
inc 
}
ca print_sorted
ac


#### 188H - Stack

This problem required to simulate a stack using an array — nothing too complicated, especially since the data never overflows and never attempts to do invalid calculations.

/*  - current character
 - current stack size
.. - service
... - stack
*/

co plus {
dec 
ac
}

co multiply {
dec 
mul [] [] []
ac
}

co number {
sub   48
inc 
set [] 
ac
}

co process {
cin 
/* end of line */
eq   10
if 
ac
/* digit - push on the stack */
gt   47
if 
ca number
eq   43
if 
ca plus
eq   42
if 
ca multiply
}

set  0
ca process
/* output the topmost element of the stack */ Tutorial of Surprise Language Round #6  Comments (0)