Writing Snake in 12 Lines of PyTorch
medium.com
medium.com
If you don't want to program CUDA kernels yourself, what's the easiest tool for the job? PyTorch, of course. Mutable by default tensors, lots of library operations and generally a pleasure to use.
The programming is really interesting - you start to think in batches - every operation is a parallel operation, it's not 1 player/item doing something, it's a whole lot of them at once - and that's really fast.
I've eventually did run into some problems - for example, ragged/sparse tensors support is not designed for this at all, and since I have variable number of items per player - this is a problem. Also, producing something like logs inside tensors is challenging - reallocation is very expensive and must be done in batches too. There are some other interesting things like launching several operations / CUDA kernels at once.
I used complex numbers and the fact that L, S, R respectively have ASCII codes 82, 83, 76 in the identities
i^(82 + 1) = -i
i^(83 + 1) = 1
i^(76 + 1) = i
to get a very compact path reconstruction.So if you use the complex numbers 1, i and -i to represent the actions “go straight”, “turn left” and “turn right” respectively, you can update a complex number representing the current heading of the snake (1 = east, i = north, -1 = west, -i = south) by multiplying it by the action. To get the snake’s current position, add up all the “current heading” numbers you’ve seen so far.
For example, in 1-line-of-code I can write "hello world". This hello world is physically lighting up individual pixels on my display. It's rendering the letters to be the shape "hello world" should be. It has antialiasing applied. All in 1 line of code!!!
This doesn't imply that a language is better than another, it's just an objective fact one might find useful to keep in mind.
The article's usage is admittedly clickbait, another recent article that popped up on the home page was titled something to the effect of "Speech Recognition in 100 lines of C++". Predictably, it turned out that they depend on a multi-million-line library.
Well done! I’m looking forward to reading how you concurrently ran 100 million mini snake games.
If I wrote my own Snake, it would probably be like 500 lines and that's OK.
I find them to be pretty useful when you are learning a new language. That said, the 500 line snake is probably more fun to play than the codegolfed snake.
Here is the core: using UDLR unlike the article
snake←{d←9 11○0J1\*'DRUL'⍳⍺ ⋄ n←(⍴⍵)|(⊣/c)+-⍣(d≡p)⊢d⊣p←-⍨/c←(⍴⍵)⊤2↑⍒,⍵ ⋄ b←(1+⌈/,⍵)@(⊂n)⊢⍵ ⋄ ¯1=n⌷⍵:1-⍨@(⊂(?∘≢⊃⊣)⍸0=⍵)⊢b ⋄ 1-⍨@(0∘<)⊢b}
Here's a rudimentary display function that displays a list of moves: ∇display moves
colours←↑(0 255 0)(0 0 0)(0 0 255)(255 0 0) ⍝ green black blue red
'b'⎕WC'Bitmap'('Bits'(0 0⍴0))('CMap'colours) ⍝ create bitmap
'f'⎕WC'Form' 'Snake demo'('Size' 500 500)('Coord' 'pixel')('Picture'b) ⍝ create form with b as the background
s←1 ¯1@(⍉↓10 10⊤2?100)⊢10 10⍴0 ⍝ start position
b.Bits←50/50⌿(¯1 0 1,⌈/,s)⍸s ⍝ display snake
:For move :In moves ⍝ loop over moves
s←move snake s ⍝ update using 'snake' function
b.Bits←50/50⌿(¯1 0 1,⌈/,s)⍸s ⍝ update bitmap
⎕DL÷50 ⍝ delay by 1/50 s
:EndFor
∇
Here's a video of the result: https://twitter.com/rak_1507/status/1557869849631670274?s=20