kk4ead / tis-100 Goto Github PK
View Code? Open in Web Editor NEWAn (eventually) comprehensive spoiler for TIS-100
License: Other
An (eventually) comprehensive spoiler for TIS-100
License: Other
I did not optimize this one much, since my solution was faster than one in document anyway.
It set initial conditions for 5 elements, and then it just subtract oldest and add new one . It use bottom right stack to remember oldest for 5s.
`@0
MOV UP,RIGHT
@1
MOV LEFT,DOWN
@2
MOV RIGHT,DOWN
@3
MOV RIGHT,ACC
MOV ACC,DOWN
MOV ACC,LEFT
@4
MOV UP,ACC
MOV ACC,DOWN
MOV ACC,LEFT
@6
MOV 0,RIGHT
MOV 0,RIGHT
MOV UP,ACC
MOV 0,RIGHT
MOV 0,RIGHT
MOV 0,RIGHT
MOV 0,RIGHT
L:
MOV ACC,RIGHT
MOV ACC,RIGHT
MOV UP,ACC
JMP L
@7
MOV 0,RIGHT
L:
SUB LEFT
MOV LEFT,RIGHT
ADD UP
MOV ACC,DOWN
JMP L
@8
MOV 0,RIGHT
L:
SUB RIGHT
MOV LEFT,RIGHT
ADD UP
MOV ACC,DOWN
JMP L
`
I do not know if you plan to cover also additional 25 problems in TIS-NET directory, but if you do post here and I can post solution in question. I did not specifically optimize those, but they are all at best speed bar or near it (those near are marked with asterisk * ), so they should be good enough for initial versions.
These are my cycle numbers per TIS-NET problems:
Sequence Merger = 573
Integer Series Calculator = 2724
Sequence Range Limiter = 338
Signal Error Corrector = 219
Subsequence Extractor = 155
Signal Prescaler = 3750
Signal Averager = 2537
Submaximum Selector = 823
Decimal Decomposer = 850
Sequence Mode Calculator = 1766*
Sequence Normalizer = 641
Image Test Pattern 3 = 1837
Image Test Pattern 4 = 1714*
Spatial Path Viewer = 1446*
Character Terminal = 766*
Back-reference Reifier = 402
Dynamic Pattern Detector = 308
Sequence Gap Interpolator = 665*
Decimal to Octal Conversion = 413
Prolonged Sequence Sorter = 1401*
Prime Factor Calculator = 6889*
Signal Exponentiator = 4260*
T20 Node Emulator = 232
T31 Node Emulator = 367
Wave Collapse Supervisor = 554
When the desired second-to-last value of OUT.E
is 1, the program hangs instead of providing the final output.
`@0
MOV UP,DOWN
@1
MOV -1,LEFT
JRO 0
@2
MOV RIGHT,ACC
L:SAV
SUB RIGHT
JGZ >
<: SWP
MOV 1,RIGHT
JMP L
: MOV 4,RIGHT
@3
MOV UP,ACC
MOV ACC,RIGHT
MOV ACC,LEFT
S:MOV RIGHT,ACC
MOV ACC,LEFT
JRO LEFT
:MOV -1,RIGHT
MOV ACC,DOWN
JMP S
<:MOV 1,RIGHT
MOV ACC,RIGHT
@4
MOV LEFT,RIGHT
S:MOV UP,LEFT
JRO LEFT
MOV LEFT,UP
MOV 0,DOWN
L:MOV DOWN,ACC
MOV ACC,RIGHT
JRO RIGHT
<:MOV -1,DOWN
MOV ACC,UP
JMP L
:MOV 1,DOWN
MOV ACC,DOWN
MOV DOWN,NIL
@5
MOV LEFT,ACC
MOV ACC,DOWN
L:SAV
SUB LEFT
JLZ <
: SWP
MOV 1,LEFT
JMP L
<: MOV 4,LEFT
@6
MOV 800,RIGHT
JRO 0
@7
MOV UP,NIL
S:MOV LEFT,UP
JRO UP
MOV UP,LEFT
MOV RIGHT,ACC
JGZ E
L:MOV LEFT,RIGHT
JRO RIGHT
MOV RIGHT,DOWN
JMP L
MOV 800,LEFT
MOV 0,DOWN
JMP E2
E:MOV ACC,LEFT
E2:MOV 0,UP
@8
S:MOV UP,ACC
MOV ACC,LEFT
JNZ S
L:MOV LEFT,ACC
SAV
SUB 700
JGZ >
<: MOV 1,LEFT
SWP
MOV ACC,LEFT
JMP L
: MOV 3,LEFT`
I used both stack elements - fill upper one first, then while it is read out, keep filling bottom one.
Trick is to exchange commands between modules (negative numbers), to be able to switch module from passing to reading etc. Second trick is to ensure synchronization by sending negative numbers back (and module lock on reading port until it receive)
Probably can be optimized further, this is my first stack problem, but already it improve over single-stack by 62 cycles.
`@0
@1
MOV 0,RIGHT
S: MOV UP,ACC
MOV ACC,RIGHT
JNZ S
MOV -1,DOWN
S2: MOV UP,ACC
MOV ACC,DOWN
JNZ S2
MOV DOWN,ACC
@4
MOV UP,ACC
MOV ACC,RIGHT
MOV 0,DOWN
S2: MOV UP,ACC
MOV ACC,DOWN
JNZ S2
MOV RIGHT,UP
MOV RIGHT,ACC
@5
MOV LEFT,ACC
MOV UP,ACC
E: MOV UP,ACC
MOV ACC,DOWN
JNZ E
MOV -1,LEFT
MOV -1,DOWN
MOV DOWN,LEFT
@7
S:MOV UP,ACC
JLZ E
MOV ACC,DOWN
JMP S
E: MOV LEFT,ACC
S2:MOV LEFT,ACC
MOV ACC,DOWN
JNZ S2
MOV -1,UP
@8`
It's possible to solve this problem using only 6 nodes, but it will probably be annoying.
This is based on my (unoptimized) 2 nodes solution for Pattern 1:
1830 CYCLES / 3 NODES / 21 INSTR
@0
@1
@2
@3
@4
@5
@6
@7
@8
MOV 18 ACC
LOOP:
SUB 1
MOV ACC RIGHT
JNZ LOOP
@9
MOV LEFT ACC
SAV
MOV RIGHT DOWN
MOV ACC DOWN
MOV 15 ACC
LOOP:
MOV 3 DOWN
MOV 0 DOWN
SUB 1
JGZ LOOP
MOV -1 DOWN
SWP
JNZ NEXT
END: JRO 0
NEXT: SWP
@10
SUB 1
NEG
MOV ACC LEFT
May be possible with 2 nodes by adapting your 1 node solution... but looks like it'll require a bit more thinking.
No optimization attempts made so far.
Node @1 is calculating difference to previous inputs, and use @0 and @2 to save previous values.
Node @5 is passing difference to @6 if positive, or @8 if negative ... and they decide if difference is above 10.
Noce @9 will get result from either positive or negative node, so it uses ANY.
'@0
MOV ACC,RIGHT
MOV RIGHT,ACC
@1
MOV UP,ACC
MOV ACC,RIGHT
SUB LEFT
MOV ACC,DOWN
MOV UP,ACC
MOV ACC,LEFT
SUB RIGHT
MOV ACC,DOWN
@2
MOV LEFT,LEFT
@5
START:
MOV UP,ACC
JLZ END
MOV ACC,RIGHT
JMP START
END:
MOV ACC,DOWN
@6
START:
MOV LEFT,ACC
SUB 10
JLZ END
MOV 1,DOWN
JMP START
END:
MOV 0,DOWN
@8
START:
MOV UP,ACC
ADD 10
JGZ END
MOV 1,RIGHT
JMP START
END:
MOV 0,RIGHT
@9
MOV ANY,DOWN
@10'
Hello, this is my enchancement for Signal Multiplexer optimized for size:
LOOP: MOV UP ACC
JGZ S=1
JEZ S=0
S=-1:MOV LEFT DOWN
MOV RIGHT ACC
JMP LOOP
S=1:MOV RIGHT DOWN
MOV LEFT ACC
JMP LOOP
S=0: MOV LEFT ACC
ADD RIGHT
MOV ACC DOWN
It was as simple as moving s=0 to the bottom, and do some fix on the logic, and it was 10 cycles more efficient than in this git current solution :). Btw, what is the used of MOV UP NIL
on your speed optimization for signal multiplexer, why it has to be there? Thanks
Definitely no optimization attempts made so far.
My best so far, can be better according to histogram:
12147 CYCLES / 6 NODES / 27 INSTR
@0
@1
MOV UP DOWN
@2
MOV UP DOWN
@3
@4
0:MOV NIL ACC
SAV
MOV UP ACC
1:SUB RIGHT
JLZ 2
SWP
ADD 1
SWP
MOV 1 RIGHT
JMP 1
2:MOV ACC RIGHT
SWP
MOV ACC DOWN
@5
0:MOV UP ACC
1:MOV ACC RIGHT
MOV ACC LEFT
MOV LEFT ACC
JLZ 2
JEZ 2
MOV RIGHT ACC
JMP 1
2:ADD RIGHT
MOV ACC DOWN
@6
@7
MOV UP DOWN
@8
MOV UP DOWN
Node @1 fills up stack. Node @1 waits 16 cycles to ensure stack is filled, and then keep passing indexes to node @4, which calculate difference from previous index and pass it to node@3 to scroll between two stacks so that desired value ends up as top value in bottom stack - which is then read by output node @7.
`@0
MOV UP,RIGHT
@1
MOV 8,ACC
L:SUB 1
JNZ L
S:
MOV UP,ACC
MOV ACC,DOWN
MOV ACC,DOWN
JMP S
@3
MOV RIGHT,ACC
JGZ _SD
JLZ _SU
JEZ _E
_SU: MOV DOWN,UP
ADD 1
JLZ _SU
JMP _E
_SD: MOV UP,DOWN
SUB 1
JGZ _SD
_E:
MOV ACC,RIGHT
@4
MOV 11,ACC
S: SUB UP
MOV ACC,LEFT
MOV UP,ACC
MOV LEFT,DOWN
JMP S
@7
MOV UP,NIL
MOV LEFT,ACC
MOV ACC,LEFT
MOV ACC,DOWN
@8`
No optimization attempts made so far.
The attached program uses shift-and-add multiplication, but is slow; determine if it can be made faster than the solution given in chapter 5.
display the book as a web page instead of just browsing the repo
No optimization attempts made so far.
Hi there,
On the main readme the "this important note about the project's status" links to:
https://github.com/kk4ead/tis-100/blob/master/CONTRIBUTING
which leads to a 404 github page, since the ".md" at the end is missing.
Not sure if this can be made any faster. Current speed is 2467 cycles, using 6 nodes and 25 instructions.
Node 1 makes 2 copies of the input. One copy gets fed into node 5, which determines which Y value the line is to start drawing it. Node 8 then feeds the Y to node 9, and increments Y.
Node 2 determines if Node 6 should increment its X value prior to Node 6 feeding its X value to node 9. Node 9 takes X, Y and draws the histogram lines, one pixel at a time.
I have additional optimization for this one, lowering my previous cycle count to 257 (from current 287). Did not post earlier, since I thought guide was not active ;p
Anyway, improvement is due to reading surplus zeros in threads that put them, instead in consumption threads:
`@0
@1
MOV 0,RIGHT
S: MOV UP,ACC
MOV ACC,RIGHT
JNZ S
MOV -1,DOWN
MOV RIGHT,NIL
S2: MOV UP,ACC
MOV ACC,DOWN
JNZ S2
MOV DOWN,NIL#UE
@4
MOV UP,RIGHT
MOV 0,DOWN
S2: MOV UP,ACC
MOV ACC,DOWN
JNZ S2
MOV RIGHT,UP
MOV DOWN,NIL
MOV RIGHT,NIL
@5
MOV LEFT,NIL
E: MOV UP,ACC
MOV ACC,DOWN
JNZ E
MOV -1,LEFT
MOV -1,DOWN
MOV DOWN,LEFT
@7
S:MOV UP,ACC
MOV ACC,DOWN
JNZ S
MOV UP,NIL
S2:MOV LEFT,ACC
MOV ACC,DOWN
JNZ S2
MOV -1,UP
@8`
It was as simple as moving the negative processing to node 10.
Node 9
MOV RIGHT, DOWN
Node 10
MOV UP,ACC
MOV ACC,DOWN
NEG
MOV ACC, LEFT
The SUB UP
instruction in nodes 6 and 8 blocks for one cycle while waiting for new input. Removing this bottleneck is expected to save about 40 cycles.
Nodes #2 and @3 calculate how many pixels of new color are in first line (until wrap or until end of new color), and that value is passed via node @0 for draw. After that node @1 loop for any full line (30 pixels) of that color, and finally for remaining pixels at start of last line.
Node @4 remembers current X for all shapes/colors (it moves it as cursor), and also detect if new line (to reset X to 0) and also pass that new line info to node @8. Node @8 remember Y coord and increase it on new line info from node @4.
Node @5 remembers new color if passed from @1, or pass old remembered color if @1 sends -1 (for other lines of same color).
Nodes @6,@10 and @11 draw one line in one row and color only. Node @11 gets width of line (originating from @1 or all way from @3 if first segment), and loop in chunks of 9 (that many MOV -3,DOWN is present in node @10). Node @10 gets X and Y from nodes @4 and @8 respectively, and then draws chunk of line up to 9 pixels long, looping as controlled by node @11.
`@0
MOV RIGHT,ACC#W
MOV ACC,DOWN
MOV ACC,DOWN
@1
S:MOV UP,ACC
MOV ACC,RIGHT
MOV UP,DOWN
MOV RIGHT,LEFT
SUB RIGHT
JEZ S
L:SUB 30
JLZ E
MOV 30,LEFT
MOV -1,DOWN
JMP L
E:ADD 30
JEZ S
MOV ACC,LEFT
MOV -1,DOWN
S:MOV LEFT,ACC
MOV ACC,RIGHT
SAV
MOV RIGHT,ACC
JLZ F
SWP
F: SWP
MOV ACC,LEFT
MOV ACC,LEFT
MOV 30,ACC
S:SAV
SUB LEFT
JLZ NL
JEZ NL
MOV -1,LEFT
JMP S
NL:SWP
MOV ACC,LEFT
SWP
L:ADD 30
JLZ L
JEZ L
JMP S
@4
S:MOV UP,RIGHT#W
MOV ACC,DOWN #X
ADD UP
SUB 30
JLZ SAME_LINE
MOV 1,DOWN #DY
JMP S
SAME_LINE:
ADD 30
MOV 0,DOWN #DY
@5
S:MOV UP,ACC#C
MOV LEFT,RIGHT#W
JLZ LOLD
SAV
MOV ACC,RIGHT
JMP S
LOLD: SWP
MOV ACC,RIGHT
@6
S:MOV LEFT,RIGHT#W
MOV LEFT,ACC#C
JLZ LOLD
SAV
MOV ACC,DOWN
JMP S
LOLD: SWP
MOV ACC,DOWN
SWP
@7
MOV LEFT,DOWN#W
@8
MOV UP,RIGHT#X
MOV ACC,RIGHT #Y
ADD UP #DY
@9
MOV LEFT,RIGHT #X
MOV LEFT,RIGHT #Y
@10
MOV LEFT,DOWN
MOV LEFT,DOWN
MOV UP,ACC
JMP L
-9:MOV ACC,DOWN
MOV ACC,DOWN
MOV ACC,DOWN
MOV ACC,DOWN
-5:MOV ACC,DOWN
MOV ACC,DOWN
MOV ACC,DOWN
-2:MOV ACC,DOWN
-1:MOV ACC,DOWN
L:JRO RIGHT
MOV -1,DOWN
@11
MOV UP,ACC#W
SAV
L:SUB 9
JLZ N
MOV -9, LEFT
JMP L
N:ADD 9
NEG
JEZ E
MOV ACC,LEFT
E:MOV 1,LEFT
`
Signal Divider - Shift & Subtract - 1553 cycles, 9 nodes, 70 instructions.
The one thing notable, is that I managed a cycle count that nearly no one else has ever managed, as it is quite a ways below the average curve. :)
Nodes 2 & 5 shifts the divider and waits for instructions on feeding it to the left.
Nodes 1 & 4 takes the divider and subtracts it from the dividend. If the result is positive, it passes on an instruction to nodes 0 & 6 to add on to the Quotient accordingly. Once node 4 is done, it passes on its instruction to node 6 to output the quotient then the remainder is output as well.
Much of this code was reused from a later TIS-NET level.
My best version so far:
1632 CYCLES / 6 NODES / 43 INSTR
@0
MOV UP RIGHT
@1
MOV NIL RIGHT
MOV NIL RIGHT
1:MOV LEFT RIGHT
MOV NIL DOWN
MOV DOWN NIL
JMP 1
@2
@3
@4
MOV UP RIGHT
MOV RIGHT ACC
ADD RIGHT
ADD RIGHT
MOV ACC DOWN
ADD DOWN
ADD DOWN
MOV ACC DOWN
MOV NIL RIGHT
MOV RIGHT UP
@5
MOV LEFT NIL
MOV UP ACC
MOV ACC LEFT
SAV
MOV UP ACC
MOV ACC LEFT
MOV ACC DOWN
MOV UP ACC
MOV DOWN UP
MOV ACC LEFT
MOV LEFT NIL
MOV ACC DOWN
SWP
MOV ACC UP
MOV NIL LEFT
@6
@7
MOV RIGHT DOWN
@8
MOV NIL RIGHT
MOV NIL RIGHT
1:MOV UP ACC
MOV ACC LEFT
MOV RIGHT ACC
MOV ACC UP
MOV RIGHT UP
MOV ACC RIGHT
MOV UP DOWN
JMP 1
According to histogram - can be optimized to 5 nodes, and less then 25 instructions, though...
I save three cycles by:
@0
S: MOV UP, ACC
JGZ 1
0: MOV 0, DOWN
JMP S
1: MOV 1, DOWN
2: MOV UP, ACC
JEZ 0
MOV 0, DOWN
JMP 2
@1
S: MOV UP, ACC
JGZ 1
0: MOV 0, DOWN
JMP S
1: MOV 2, DOWN
2: MOV UP, ACC
JEZ 0
MOV 0, DOWN
JMP 2
@2
S: MOV UP, ACC
JGZ 1
0: MOV 0, DOWN
JMP S
1: MOV 3, DOWN
2: MOV UP, ACC
JEZ 0
MOV 0, DOWN
JMP 2
@3
S: MOV UP, ACC
JGZ 1
0: MOV 0, DOWN
JMP S
1: MOV 4, DOWN
2: MOV UP, ACC
JEZ 0
MOV 0, DOWN
JMP 2
@4
MOV UP, RIGHT
@5
MOV UP, ACC
ADD LEFT
MOV ACC, DOWN
@6
MOV UP, ACC
ADD RIGHT
MOV ACC, DOWN
@7
MOV UP, LEFT
@8
MOV UP, RIGHT
@9
MOV UP, ACC
ADD LEFT
MOV ACC, DOWN
On the statistics screen for Segment 22280: Signal Multiplexer, there is a solution displayed with 7 or 9 nodes and about 200 cycles. Determine this solution and add it to chapter 3.
First the source for this optimization:
I was on 201 cycles for Differential Converter, while you have 200 listed - my solution was almost identical but mirrored. But the difference in 1 (one!) cycle came from final MOV
being just one line lower then your:
@9
MOV LEFT ACC
NEG
MOV ACC DOWN
vs
@8
SUB RIGHT
MOV ACC DOWN
MOV 0 ACC
"Nice fact" I've though then... and then have reached this puzzle.
"Wait... what if we move the MOV
here too?"
Here's the result of switching the order of commands in the NO:
paths:
1 whole cycle is saved :D
Almost optimal - it is needed 551 cycles to output 139 pixels in 39 lines, and this solution only use 559 cycles. Optimizations are, among others:
`@0
@1
MOV UP,RIGHT #X,W
MOV UP,DOWN #Y,H
@2
MOV LEFT,DOWN#X,W
@4
MOV UP,ACC#Y
SAV
MOV UP,ACC#H
L:SWP
MOV ACC,DOWN#Y
ADD 1
SWP
SUB 1#H
JEZ E
MOV -4,RIGHT
JMP L
E:MOV -100,RIGHT
@5
S:MOV UP,ACC#X
SAV
MOV 6,ACC
SUB UP#W
X:SWP
MOV ACC,DOWN#X
SWP
MOV ACC,DOWN#DW
JRO LEFT
@8
MOV UP,RIGHT
@9
MOV UP,DOWN#X
MOV LEFT,DOWN#Y
JRO UP#DW
MOV 3,DOWN
MOV 3,DOWN
MOV 3,DOWN
MOV 3,DOWN
MOV 3,DOWN
MOV -1,DOWN
`
@0
MOV UP ACC
JEZ H
MOV 1 ACC
H: MOV ACC DOWN
@1
MOV UP ACC
JEZ H
MOV 2 ACC
H: MOV ACC DOWN
@2
MOV UP ACC
JEZ H
MOV 3 ACC
H: MOV ACC DOWN
@3
MOV UP ACC
JEZ H
MOV 4 ACC
H: MOV ACC DOWN
@4
MOV UP RIGHT
@5
MOV UP ACC
ADD LEFT
MOV ACC RIGHT
@6
MOV UP ACC
ADD LEFT
ADD RIGHT
MOV ACC DOWN
MOV ACC DOWN
@7
MOV UP LEFT
@9
SUB UP
JLZ GD
MOV 0 ACC
JRO 2
GD: NEG
MOV ACC DOWN
MOV UP ACC
Some writeups could be clearer / more detailed.
This is optimization based on original kk4ead solution:
'@0
@1
MOV UP,DOWN
@4
MOV UP ACC
MOV ACC RIGHT
MOV ACC DOWN
@5
S:MOV LEFT,ACC
JEZ E
MOV -1,DOWN
JMP S
E:MOV 1,DOWN
@7
MOV ACC RIGHT
MOV RIGHT ACC
@8
START: MOV UP ACC
JNZ END
MOV LEFT,DOWN
MOV 0,LEFT
JMP START
END:
ADD LEFT
MOV ACC,LEFT
@9
MOV -1,ACC
ADD 1
JRO UP
MOV ACC,DOWN
@10
'
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.