* feat(tools): add seed/solution restore script * chore(curriculum): remove empty sections' markers * chore(curriculum): add seed + solution to Chinese * chore: remove old formatter * fix: update getChallenges parse translated challenges separately, without reference to the source * chore(curriculum): add dashedName to English * chore(curriculum): add dashedName to Chinese * refactor: remove unused challenge property 'name' * fix: relax dashedName requirement * fix: stray tag Remove stray `pre` tag from challenge file. Signed-off-by: nhcarrigan <nhcarrigan@gmail.com> Co-authored-by: nhcarrigan <nhcarrigan@gmail.com>
		
			
				
	
	
		
			197 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			197 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | |
| id: 5a23c84252665b21eecc8038
 | |
| title: Subleq
 | |
| challengeType: 5
 | |
| forumTopicId: 302328
 | |
| dashedName: subleq
 | |
| ---
 | |
| 
 | |
| # --description--
 | |
| 
 | |
| [Subleq](https://rosettacode.org/wiki/eso:Subleq) is an example of a [One-Instruction Set Computer (OISC)](https://en.wikipedia.org/wiki/One_instruction_set_computer).
 | |
| 
 | |
| It is named after its only instruction, which is **SU**btract and **B**ranch if **L**ess than or **EQ**ual
 | |
| 
 | |
| to zero.
 | |
| 
 | |
| Your task is to create an interpreter which emulates such a machine.
 | |
| 
 | |
| The machine's memory consists of an array of signed integers. Any reasonable word size is fine, but the memory must be
 | |
| 
 | |
| able to hold negative as well as positive numbers.
 | |
| 
 | |
| Execution begins with the instruction pointer aimed at the first word, which is address 0. It proceeds as follows:
 | |
| 
 | |
| <ol>
 | |
|   <li>Let A, B, and C be the value stored in the three consecutive words in memory starting at the instruction pointer.</li>
 | |
|   <li>Advance the instruction pointer 3 words to point at the address after the one containing C.</li>
 | |
|   <li>If A is -1, then a character is read from standard input and its code point stored in the address given by B. C
 | |
|     is unused.</li>
 | |
|   <li>If B is -1, then the number contained in the address given by A is interpreted as a code point and the
 | |
|     corresponding character output. C is again unused.</li>
 | |
|   <li>Otherwise, both A and B are treated as the addresses of memory locations. The number contained in the address
 | |
|     given by A is subtracted from the number at the address given by B (and the result stored back in address B). If
 | |
|     the result is zero or negative, the value C becomes the new instruction pointer.</li>
 | |
|   <li>If the instruction pointer becomes negative, execution halts.</li>
 | |
| </ol>
 | |
| 
 | |
| Other negative addresses besides -1 may be treated as equivalent to -1, or generate an error, as you see fit.
 | |
| 
 | |
| Your solution should accept a program to execute on the machine, separately from the input fed to the program itself.
 | |
| 
 | |
| This program should be in raw subleq "machine code" - whitespace-separated decimal numbers, with no symbolic names or
 | |
| 
 | |
| other assembly-level extensions, to be loaded into memory starting at address 0. Show the output of your solution when
 | |
| 
 | |
| fed this "Hello, world!" program. (Note that the example assumes ASCII or a superset of it, such as any of the Latin-N
 | |
| 
 | |
| character sets or Unicode. You may translate it into another character set if your implementation is on a
 | |
| 
 | |
| non-ASCiI-compatible environment.)
 | |
| 
 | |
| <pre>15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0</pre>
 | |
| 
 | |
| Which corresponds to something like this in a hypothetical assembler language:
 | |
| 
 | |
| <pre>start:
 | |
|     zero, message, -1
 | |
|     message, -1, -1
 | |
|     neg1, start+1, -1
 | |
|     neg1, start+3, -1
 | |
|     zero, zero, start
 | |
| zero: 0
 | |
| neg1: -1
 | |
| message: "Hello, world!\n\0"
 | |
| </pre>
 | |
| 
 | |
| # --instructions--
 | |
| 
 | |
| Write a function that takes an array of integers as a parameter. This represents the memory elements. The function
 | |
| 
 | |
| should interpret the sequence and return the output string. For this task, assume that there is no standard input.
 | |
| 
 | |
| # --hints--
 | |
| 
 | |
| `Subleq` should be a function.
 | |
| 
 | |
| ```js
 | |
| assert(typeof Subleq == 'function');
 | |
| ```
 | |
| 
 | |
| `Subleq([15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 0])` should return a string.
 | |
| 
 | |
| ```js
 | |
| assert(
 | |
|   typeof Subleq([
 | |
|     15,
 | |
|     17,
 | |
|     -1,
 | |
|     17,
 | |
|     -1,
 | |
|     -1,
 | |
|     16,
 | |
|     1,
 | |
|     -1,
 | |
|     16,
 | |
|     3,
 | |
|     -1,
 | |
|     15,
 | |
|     15,
 | |
|     0,
 | |
|     0,
 | |
|     -1,
 | |
|     72,
 | |
|     101,
 | |
|     108,
 | |
|     108,
 | |
|     111,
 | |
|     44,
 | |
|     32,
 | |
|     119,
 | |
|     111,
 | |
|     114,
 | |
|     108,
 | |
|     100,
 | |
|     33,
 | |
|     0
 | |
|   ]) == 'string'
 | |
| );
 | |
| ```
 | |
| 
 | |
| `Subleq([15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 0])` should return `"Hello, world!"`.
 | |
| 
 | |
| ```js
 | |
| assert.equal(
 | |
|   Subleq([
 | |
|     15,
 | |
|     17,
 | |
|     -1,
 | |
|     17,
 | |
|     -1,
 | |
|     -1,
 | |
|     16,
 | |
|     1,
 | |
|     -1,
 | |
|     16,
 | |
|     3,
 | |
|     -1,
 | |
|     15,
 | |
|     15,
 | |
|     0,
 | |
|     0,
 | |
|     -1,
 | |
|     72,
 | |
|     101,
 | |
|     108,
 | |
|     108,
 | |
|     111,
 | |
|     44,
 | |
|     32,
 | |
|     119,
 | |
|     111,
 | |
|     114,
 | |
|     108,
 | |
|     100,
 | |
|     33,
 | |
|     0
 | |
|   ]),
 | |
|   'Hello, world!'
 | |
| );
 | |
| ```
 | |
| 
 | |
| # --seed--
 | |
| 
 | |
| ## --seed-contents--
 | |
| 
 | |
| ```js
 | |
| function Subleq(mem) {
 | |
| 
 | |
| }
 | |
| ```
 | |
| 
 | |
| # --solutions--
 | |
| 
 | |
| ```js
 | |
| function Subleq(mem) {
 | |
|   var out = '';
 | |
|   var instructionPointer = 0;
 | |
|   do {
 | |
|     var a = mem[instructionPointer];
 | |
|     var b = mem[instructionPointer + 1];
 | |
|     if (a === -1) {
 | |
|     } else if (b === -1) {
 | |
|       out += String.fromCharCode(mem[a]);
 | |
|     } else {
 | |
|       mem[b] -= mem[a];
 | |
|       if (mem[b] < 1) {
 | |
|         instructionPointer = mem[instructionPointer + 2];
 | |
|         continue;
 | |
|       }
 | |
|     }
 | |
|     instructionPointer += 3;
 | |
|   } while (instructionPointer >= 0);
 | |
| 
 | |
|   return out;
 | |
| }
 | |
| ```
 |