Latar Belakang
Adler-32 adalah checksum 32-bit yang ditemukan oleh Mark Adler pada tahun 1995 yang merupakan bagian dari perpustakaan zlib yang banyak digunakan (juga dikembangkan oleh Adler). Adler-32 tidak dapat diandalkan seperti pemeriksaan redundansi siklik 32-bit , tetapi - setidaknya dalam perangkat lunak - lebih cepat dan lebih mudah untuk diterapkan.
Definisi
Misalkan B = [b 1 , ⋯, b n ] menjadi array byte.
Checkum Adler-32 B didefinisikan sebagai hasil dari rendah + 65536 × tinggi , di mana:
rendah: = ((1 + b 1 + ⋯ + b n ) mod 65521)
tinggi: = (((1 + b 1 ) + (1 + b 1 + b 2 ) + ⋯ (1 + b 1 + ⋯ + b n )) mod 65521)
Tugas
Diberikan array byte sebagai input, hitung dan kembalikan checksum Adler-32-nya, patuhi yang berikut.
Anda dapat mengambil input sebagai array byte atau bilangan bulat, atau sebagai string.
Dalam kedua kasus, hanya byte yang sesuai dengan karakter ASCII yang dapat dicetak yang akan muncul di input.
Anda dapat mengasumsikan bahwa panjang input akan memenuhi 0 <panjang ≤ 4096 .
Jika Anda memilih untuk mencetak output, Anda dapat menggunakan basis positif apa pun hingga dan termasuk 256.
Jika Anda memilih unary, pastikan interpreter dapat menangani hingga 2 32 - 983056 byte output pada mesin dengan 16 GiB RAM.
Built-in yang menghitung checksum Adler-32 dilarang.
Aturan standar kode-golf berlaku.
Uji kasus
String: "Eagles are great!"
Byte array: [69, 97, 103, 108, 101, 115, 32, 97, 114, 101, 32, 103, 114, 101, 97, 116, 33]
Checksum: 918816254
String: "Programming Puzzles & Code Golf"
Byte array: [80, 114, 111, 103, 114, 97, 109, 109, 105, 110, 103, 32, 80, 117, 122, 122, 108, 101, 115, 32, 38, 32, 67, 111, 100, 101, 32, 71, 111, 108, 102]
Checksum: 3133147946
String: "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
Byte array: [126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126]
Checksum: 68095937
String: <1040 question marks>
Byte array: <1040 copies of 63>
Checksum: 2181038080
sumber
Jawaban:
Jelly,
1917 byteCobalah online!
sumber
⁹²¤
Mathematica, 46 byte
Fungsi anonim yang mengambil array integer dan mengembalikan Adler-32, dengan beberapa peningkatan dari miles dan Martin (lihat komentar).
miles 'juga 46 byte , tetapi lebih cepat:
sumber
Julia,
7346 byteIni adalah fungsi anonim yang menerima array dan mengembalikan integer. Untuk menyebutnya, tetapkan ke variabel.
Kami menggabungkan
sum(x) + 1
dansum(cumsum(x) + 1)
menjadi sebuah array, di manax
array input, dan mengambil masing-masing modulo 65521. Kami kemudian menghitung produk titik dengan 1 dan 4 8 , yang memberi kita(sum(x) + 1) + 4^8 * sum(cumsum(x) + 1)
, yang persis rumus Adler-32.Cobalah online!(Termasuk semua kasus uji)
Disimpan 27 byte berkat Sp3000 dan Dennis!
sumber
x86-64 fungsi kode mesin:
3332 byte (atau3130 byte denganint[]
input, bukanchar[]
)fungsi kode mesin x86-32: 31 byte
Sebagai fragmen kode inline-asm GNU C: menyimpan
2B1B (hanyaret
insn).Sumber dan test driver yang dikomentari di github
Versi 64bit dapat dipanggil langsung dari C dengan standar Sistem V x86-64 ABI (menggunakan 2 dummy args untuk mendapatkan args di regs yang saya inginkan). Konvensi panggilan khusus tidak biasa untuk kode asm, jadi ini adalah fitur bonus.
Kode mesin 32bit menghemat 1B, karena menggabungkan bagian tinggi dan rendah dengan
push16/push16 => pop32
hanya bekerja dalam mode 32bit. Fungsi 32bit membutuhkan konvensi pemanggilan kustom. Kita seharusnya tidak berpegang teguh pada itu, tetapi panggilan dari C membutuhkan fungsi wrapper.Setelah memproses 4096
~
(ASCII 126) bytehigh = 0x3f040000, low = 0x7e001
,. Jadihigh
bit yang paling signifikan belum ditetapkan. Kode saya mengambil keuntungan dari ini, masukeax
keedx:eax
dengancdq
sebagai cara memusatkan perhatianedx
.0x40 - 0x20
= 32 byte.Sumber NASM yang dikomentari:
Trik:
xchg eax, r32
adalah satu byte; lebih murah daripada mov. 8086 membutuhkan data dalam kapak untuk hal-hal yang jauh lebih banyak daripada> = 386, sehingga mereka memutuskan untuk menghabiskan banyak ruang opcode pada yang sekarang-jarang digunakanxchg ax, r16
.Mencampur push64 dan push16 untuk menggabungkan tinggi dan rendah ke dalam satu register menyimpan instruksi perpindahan data reg-reg sekitar dua
div
detik. Versi 32bit dari trik ini bekerja lebih baik:push16 / push16 / pop32
totalnya hanya 5B, bukan 6.Karena kita push / pop, ini tidak aman untuk asline inm di SysV amd64 ABI (dengan zona merah) .
Saya juga dianggap menggunakan
rcx
sebagai indeks array, bukannya memiliki dua loop counter, tetapi adler32 (s)! = Adler32 (terbalik (s)). Jadi kami tidak bisa menggunakanloop
. Menghitung dari -len hingga nol dan menggunakanmovzx r32, [rsi+rcx]
terlalu banyak byte.Jika kita ingin mempertimbangkan untuk menambahkan pointer sendiri, kode 32bit mungkin adalah cara yang harus dilakukan. Bahkan ABI x32 (pointer 32-bit) tidak cukup, karena
inc esi
2B pada amd64, tetapi 1B pada i386. Tampaknya sulit untuk mengalahkanxor eax,eax
/lodsb
/loop
: 4B total untuk mendapatkan setiap elemen pada gilirannya nol-diperpanjang menjadi eax.inc esi
/movzx r32, byte [esi]
/loop
adalah 5B.scas
adalah pilihan lain untuk menambah pointer dengan instruksi 1B dalam mode 64bit. (rdi
/edi
bukannyarsi
, jadi kami akan mengambil pointer pointer dirdi
). Namun, kami tidak dapat menggunakan hasil flagscas
sebagai kondisi loop, karena kami tidak ingin mempertahankan eax zeroed. Alokasi register yang berbeda mungkin dapat menyimpan byte setelah loop.int[]
memasukkanPengambilan fungsi penuh
uint8_t[]
adalah jawaban "utama", karena ini merupakan tantangan yang lebih menarik. Membongkar keint[]
adalah hal yang tidak masuk akal untuk meminta penelepon kami melakukannya dalam bahasa ini, tetapi hal itu menghemat 2B.Jika kita mengambil input kita sebagai array bilangan bulat 32bit, kita dapat menyimpan satu byte dengan mudah (gunakan
lodsd
dan gantixor eax,eax / cdq
hanya denganxor edx,edx
).Kita dapat menyimpan byte lain dengan memusatkan edx dengan
lodsd
/cdq
, dan mengatur ulang loop sehingga memuat elemen 0 terminating sebelum keluar. (Kami masih menganggap itu ada, meskipun ini adalah arrayint
, bukan string).Saya juga membuat versi yang belum diuji yang menggunakan
scasd
(versi 1Badd edi,4
) danadd eax, [rdi]
bukannyalodsd
, tetapi juga 30 byte. Penghematan dari memilikihigh
di eax pada akhir loop diimbangi oleh kode yang lebih besar di tempat lain. Ini memiliki keuntungan tidak tergantung pada0
elemen terminating dalam input, yang mungkin tidak masuk akal untuk array yang tidak dibongkar dimana kita juga diberi panjangnya secara eksplisit.C ++ 11 test driver
Lihat tautan github. Jawaban ini menjadi terlalu besar, dan driver tes mendapat lebih banyak fitur dengan kode yang lebih besar.
sumber
int[]
jika perlu, atau menyimpan lebih dari 4 byte kode atau sesuatu. Saya tidak punya masalah menghadirkan solusi untukadler32(int[])
masalah ini, tetapi saya merasaadler32(char[])
masalahnya lebih menarik, karena itu adalah fungsi adler32 yang sebenarnya. Itu yang saya benar-benar ingin menjadi golf di ASM. (Dan saya ingin sekali menyimpan satu byte lagi, karena dalam kehidupan nyata asm, 33 byte = 48 byte jika fungsi selanjutnya menggunakanALIGN 16
). Saya kira saya akan terus bermain golf keduanya.do{}while(--len)
gaya loop bukan awhile(len--){}
.MATL , 22 byte
Input dapat berupa array angka atau string ASCII yang sesuai.
Cobalah online!
Penjelasan
sumber
Sebenarnya, 36 byte
Cobalah online!
Penjelasan:
sumber
Java, 84 byte
Jika solusi Java selalu dianggap sebagai kode yang dapat dikompilasi, beri tahu saya.
Tidak disatukan
Catatan
Anda harus mengonversi input
String
menjadiint[]
(int[]
lebih pendek satu byte daribyte[]
atauchar[]
).Keluaran
sumber
Piet, 120 Codel
Dengan ukuran kode 20:
Catatan / Bagaimana cara kerjanya?
Karena tidak mungkin menggunakan array atau string sebagai input, program ini bekerja dengan mengambil serangkaian bilangan bulat (mewakili karakter ascii) sebagai input. Saya berpikir tentang menggunakan input karakter pada awalnya tetapi berjuang untuk menemukan solusi yang bagus untuk penghentian, jadi sekarang berakhir ketika ada angka yang lebih kecil dari 1 dimasukkan. Awalnya hanya nilai negatif untuk penghentian, tetapi saya harus mengubah inisialisasi setelah menulis program, jadi sekarang saya tidak bisa cocok dengan yang diperlukan
2
, hanya1
(26/45 pada gambar jejak). Ini tidak masalah karena karena sesuai aturan tantangan, hanya karakter ascii yang dapat dicetak yang diizinkan.Berjuang untuk waktu yang lama dengan memasuki kembali loop, meskipun pada akhirnya saya menemukan solusi yang cukup elegan. Tidak
pointer
atauswitch
operasi, hanya interpreter berjalan ke dinding sampai transisi kembali ke codel hijau untuk membaca input (43-> 44 pada gambar jejak).Pengakhiran loop dilakukan dengan menduplikasi input terlebih dahulu, menambahkan 1 dan kemudian memeriksa apakah lebih besar dari 1. Jika ya, pemilih kode dipicu dan eksekusi berlanjut di jalur yang lebih rendah. Jika tidak, program akan melanjutkan ke kiri (Kode kuning cerah, 31/50 pada gambar jejak).
Ukuran input yang didukung bergantung pada implementasi juru bahasa, meskipun akan mungkin untuk mendukung input yang besar dan sewenang-wenang dengan juru bahasa yang tepat (Misalnya, juru bahasa Java yang menggunakan
BigInteger
nilai internal)Hanya melihat bahwa pengaturan termasuk yang tidak perlu
DUP
danCC
(7-> 8-> 9 di gambar jejak). Tidak tahu bagaimana itu terjadi. Ini secara efektif adalah noop sekalipun, ia mengaktifkan pemilih kode 16 kali yang menghasilkan tidak ada perubahan.Npiet melacak gambar
Setup dan loop pertama:
Pengakhiran loop, output dan keluar:
Keluaran
Maafkan saya jika saya hanya memasukkan satu output, hanya butuh waktu lama untuk memasukkan: ^)
Jejak Npiet untuk [65, -1]
sumber
C89, 70 byte
Untuk menguji (kompilasi dengan
gcc -std=c89 -lm golf.c
):sumber
zlib
terlihat sumbernya? Hm ...for
bukannyawhile
:for(h=0,l=1;*B;)h+=l+=*B++;
Labyrinth ,
37363231 byteCobalah online!
Input sebagai daftar bilangan bulat. Program berakhir dengan kesalahan (yang pesan kesalahannya masuk ke STDERR).
Penjelasan
Primer labirin:
_
.Meskipun kode dimulai dengan "ruang" 4x2, itu sebenarnya dua loop dua-dua terpisah yang diperas. IP kebetulan menempel satu loop pada satu waktu karena nilai stack.
Jadi kode dimulai dengan loop 2x2 (searah jarum jam) yang membaca input saat menghitung jumlah awalan:
Sekarang kita memiliki semua jumlah awalan pada tumpukan aux , serta salinan jumlah atas semua nilai dan
0
dari EOF pada main . Dengan itu, kita memasukkan loop 2x2 (searah jarum jam) yang menjumlahkan semua jumlah awalan untuk dihitungHIGH
.Stack utama sekarang memiliki
LOW - 1
danHIGH
nol, kecuali kita belum mengambil modulo. Sisa kode sepenuhnya linier:IP sekarang menemui jalan buntu dan berbalik. The
+
dan*
pada dasarnya tidak ada ops, karena angka nol di bagian bawah tumpukan. The36
sekarang ternyata bagian atas utama dalam63
, tetapi dua{{
tarik dua nol dari aux di atasnya. Kemudian%
coba bagi dengan nol yang mengakhiri program.Perhatikan bahwa Labyrinth menggunakan bilangan bulat presisi arbitrer jadi tunda modulo sampai akhir jumlah tidak akan menyebabkan masalah dengan bilangan bulat bilangan bulat.
sumber
Python 2,
6058 bytePendekatan yang cukup mudah. Ini adalah program lengkap yang mengambil daftar bilangan bulat melalui STDIN, mis
[72, 105, 33]
.(Terima kasih kepada @xnor untuk tip aliasing / inisialisasi yang luar biasa)
sumber
H=h=65521
inisialisasih
sementara aliasing 65521.J, 30 byte
Ini mungkin bisa lebih padat dengan kereta yang berbeda.
Pemakaian
Di sini
x $ y
membuat daftar denganx
salinany
.Penjelasan
sumber
Oktaf,
5250 byteDisimpan 2 byte berkat @LuisMendo
Mengambil array bilangan bulat sebagai input.
rendah diambil dari elemen terakhir tinggi (sebelum penjumlahan) daripada menghitung jumlah secara eksplisit, menghemat total ... 1 byte !
Sampel dijalankan pada ideone .
sumber
+B
. Saya kira spec input mengatakan Anda dapat mengambil bilangan bulat, jadi mungkin saya hanya akan melakukannya.CJam,
3029 byteInput sebagai daftar bilangan bulat.
Uji di sini.
Penjelasan
sumber
Perl 6 , 60 byte
Penjelasan:
Uji:
sumber
Python 3 (79 byte)
Berdasarkan solusi R. Kap.
Saya mengganti perkalian dengan satu shift dan melepaskan sepasang tanda kurung.
Karena saya tidak dapat memposting komentar, saya membuat jawaban baru.
sumber
Skema, 195 byte
Jika bukan karena semua kurung itu ...
sumber
Haskell,
5450 byteContoh penggunaan:
g [69,97,103,108,101,115,32,97,114,101,32,103,114,101,97,116,33]
->918816254
.scanl
termasuk nilai awal (->1
) dalam daftar (->[1,1+b1,1+b1+b2,..]
), jadisum
dimatikan oleh1
, yang diperbaiki oleh prepending-1
ke daftar sebelum menjumlahkan.Sunting: Terima kasih @xnor untuk 4 byte.
sumber
m
:m=(`mod`65521).sum g x=m(-1:scanl(+)1x)*4^8+m(1:x)
. Mungkin ada cara yang lebih baik untuk memperbaiki jumlah daripada mengawali.JavaScript (ES7),
5250 byteES6 membutuhkan 51 byte (ganti 4 ** 8 dengan 65536). Jika Anda menginginkan versi string, maka untuk 69 byte:
Sunting: Disimpan 2 byte berkat @ user81655.
sumber
Menerima fungsi ARM Thumb-2
uint8_t[]
: 40 byte (36B untuk ABI non-standar danint[]
)Fitur-fitur: modulo yang tidak ditangguhkan, sehingga input ukuran arbitrer baik-baik saja. Tidak benar-benar menggunakan instruksi pembagian, jadi itu tidak lambat. (err, setidaknya bukan karena alasan itu: P)
Penghematan dari mengikuti aturan yang tidak terlalu ketat:
uint32_t[]
array.Jadi, kasus terbaik adalah 36B.
0x28 = 40 byte
Catatan:
Alih-alih
log%m
pada akhirnya, kita melakukannyaif(low>=m) low-=m
di dalam loop. Jika kita melakukan rendah sebelum tinggi, kita tahu bahwa tidak ada yang bisa melebihi2*m
, jadi modulo hanya masalah pengurangan atau tidak. Acmp
dan predicatedsub
hanya 6B dalam mode Thumb2. Idi standar untuk%
adalah 8B dalam mode Thumb2:adler(char *)
Versi panjang implisit adalah ukuran kode yang sama dengan panjang eksplisitadler(uint8_t[], uint32_t len)
. Kita dapat mengatur flag untuk kondisi loop-exit dengan satu instruksi 2B.Versi implisit-panjang memiliki keuntungan bekerja dengan benar dengan string kosong, daripada mencoba untuk mengulang 2 ^ 32 kali.
berkumpul / kompilasi dengan:
atau
Tanpa
-static
, proses yang berjalan di bawahqemu-arm
tidak menemukan itu penghubung dinamis. (Dan ya, saya menginstal ARM cross-devel setup hanya untuk jawaban ini, karena saya pikir ide predicated-kurangi saya rapi.) Di amd64 Ubuntu, instalgcc-arm-linux-gnueabi
,g++-arm-linux-gnueabi
. Saya menemukangdb-arm-none-eabi
semacam bekerja menghubungkan keqemu-arm -g port
.Sumber yang dikomentari:
test-adler32.cpp
memiliki kasus uji yang sama danmain()
untuk jawaban x86-64 saya, tetapi memulai dengan cara ini:sumber
Fungsi kode mesin x86 16bit: 32 byte menggunakan konvensi pemanggilan kustom
Args dalam register, dan tidak melestarikan regs selain bp (dan sp).
Dalam kode 16bit, kami mengembalikan nilai 32bit dalam
dx:ax
pasangan register. Ini berarti kita tidak perlu menghabiskan petunjuk setiap penggabunganhigh
danlow
menjadieax
. (Ini akan menghemat byte dalam kode 32 dan 64 bit, tetapi kami hanya bisa membenarkan pembongkaran pekerjaan ini ke pemanggil dalam kode 16bit.)Sumber dan driver tes yang dikomentari pada github (untuk x86 16, 32, dan 64bit, dan ARM).
0x120 - 0x100 = 32 byte
Diuji dengan merakit kode yang sama untuk mode 32bit, jadi saya bisa menyebutnya (dengan fungsi pembungkus) dari C yang dikompilasi dengan
-m32
. Bagi saya, mode 16bit agak menarik, panggilan sistem DOS tidak. Semua instruksi memiliki operan eksplisit, kecualiloop
danlodsb
, jadi perakitan untuk mode 32bit menggunakan awalan ukuran operan. Instruksi yang sama, pengkodean yang berbeda. Tetapilodsb
dalam mode 32bit akan digunakan[esi]
, jadi versi untuk-pengujian ini bekerja dengan pointer 32-bit (karena kita tidak melakukan kenaikan-perbandingan alamat atau matematika / pointer).Tidak ada ketidakcocokan. Harness pengujian saya mencetak pesan jika ada ketidakcocokan.
Dengan register 16bit, kami tidak dapat menunda pengurangan modulo sampai setelah loop. Ada perbedaan yang menarik antara 16bit dan ukuran operan lainnya:
m = 65521
(0xFFF1
) lebih dari setengah 65536. Mengurangkanm
pada carry menjaga nilainya di bawah 2 * m, bahkan jikahigh=0xFFF0 + 0xFFF0
. Setelah loop, bandingkan dan kurangi akan melakukan trik, bukan adiv
.Saya datang dengan teknik baru untuk mengurangi register modulo setelah add yang dapat menghasilkan barang bawaan . Alih-alih membidik bagian atas input untuk
div
, gunakansetc dl
untuk membuat dividen 32bit yang menahan hasil tambah yang tidak terpotong (dh
sudah nol). (div
Apakah 32b / 16b => 16bit divisi.)setcc
(3 byte) diperkenalkan dengan 386. Untuk menjalankan ini pada 286 atau sebelumnya, yang terbaik yang saya buat menggunakan instruksi tidak berdokumensalc
(atur AL dari carry) . Ini adalah opcode satu byte untuksbb al,al
, jadi kita bisa menggunakansalc
/neg al
sebelum melakukanxchg ax, dx
(yang kita perlukan). Tanpasalc
, ada urutan 4B:sbb dx,dx
/neg dx
. Kami tidak dapat menggunakan 3Bsbb dx,dx
/inc dx
, karena itu akan ditirusetnc
daripadasetc
.Saya mencoba menggunakan ukuran operan 32bit alih alih menangani carry, tetapi bukan hanya
add
instruksi yang memerlukan awalan ukuran operan. Instruksi pengaturan konstanta dan seterusnya juga membutuhkan awalan ukuran operan, sehingga akhirnya tidak menjadi yang terkecil.sumber
Pyth,
252423 byteTerima kasih 1 byte @Jakube .
1 byte lebih banyak berkat @Jakube .
Cobalah online!
Terjemahan jawaban saya di Jelly .
sumber
Perl 5, 43 byte
42 byte, ditambah 1 untuk
-aE
bukan-e
Input adalah bilangan bulat desimal, dipisahkan oleh spasi.
Ujung topiku untuk Sp3000 , dari siapa saya mengambil ide untuk jawaban ini.
Bagaimana itu bekerja:
-a
,$.
mulai dari 1 dan@F
merupakan array input.$h
mulai dari 0.$_
digunakan olehmap
sebagai placeholder untuk setiap elemen array.map$h+=$.+=$_,@F
berarti bahwa untuk setiap elemen dalam@F
kita menambahkan elemen itu untuk$.
dan kemudian menambahkan$.
ke$h
.$.%65521+$h%65521*4**8
(yaitu,($. % 65521) + ( ($h % 65521) * (4**8) )
dansay
(mencetak) hasilnya.sumber
Faktor,
112109103 byteSekarang , ini adalah terjemahan harfiah dari algoritma dalam pertanyaan ... sekarang saya benar-benar membuatnya, Anda tahu, benar.
Tidak Disatukan:
Mengharapkan urutan angka atau string apa pun (tidak banyak perbedaan, meskipun secara teknis tidak sama).
Saya tidak tahu bagaimana ini akan bekerja untuk batas yang diberikan pada versi Factor yang dikompilasi dengan ukuran kata 32-bit, tetapi pada mesin 2.2GHz 6GB 64-bit saya:
sumber
Ruby, 91 byte
sumber
Clojure, 109 byte
Berdasarkan solusi @ Mark Adler .
Tidak disatukan
Pemakaian
sumber
Javascript (130 Karakter Ber Golf)
Tidak disatukan
Golf
Rekatkan ke Konsol Pengembang dan berikan Array Bytes EG:
Dan itu akan mengembalikan checksum ke konsol
sumber
TMP, 55 byte
3a1.3b0.1;4+a>T8%a>xFFF14+b>a8%b>xFFF11~5<b>164|b>a2$b$
Implementasi di Lua dapat ditemukan di sini: http://preview.ccode.gq/projects/TMP.lua
sumber
Python 3.5, 82 byte:
( -1 byte terima kasih kepada Neil ! )
( -1 byte terima kasih kepada mathmandan ! )
( -4 byte terima kasih kepada Dennis ! )
lambda
Fungsi anonim . Menerima array byte, menerapkan seluruh algoritma ke array, dan menampilkan hasilnya. Berhasil bekerja untuk semua kasus uji. Anda memanggil ini dengan menetapkan variabel ke sana, dan kemudian memanggil variabel itu sama seperti Anda memanggil fungsi normal. Jika Anda menggunakan shell, maka ini seharusnya dihasilkan tanpa fungsi cetak. Namun, jika tidak, maka Anda harus membungkus panggilan fungsi dalamprint()
fungsi untuk benar-benar melihat output.Cobalah online! (Ideone)
sumber
(E+15)
is actually a byte longer than65536
.4**8
is a byte shorter than65536
.Fission, 324 bytes
Fair warning, the only implementation I've tested this on is my own port of the language to F#. It's not golfed, mainly because I found it easier to have a couple of long runs while my prime constant cooled along the bottom, so I may come back and tweak it.
How does it work?
R'~++Y++~'L
block fuses a 256 constant and launches it downwards, setting the mass multiplier of the reactor directly below it.R'~++A++~'A
block fuses another 256 and launches it up towards the reactor above, which fissions the particle into two mass multiples of65536
mass each, launching them left and right (where the right particle is immediately destroyed by the terminator).65521
(our large prime).Z
) at the end of the run causes the particle to duplicate the prime, sending one back to the right where it ultimately sets the stored mass of the fission reactor (^
). This is how we'll be applying the modulus operator to the H block.<
) we'll be using for the L block.|S
"cooling tower".\Y/
fuses the L block (which comes in through the left channel) and the H block (which comes in through the right channel), then slams them into a terminator which sets the exit code to the fused mass.sumber
*
, which is how I'm returning the output. I'll see if I can find another interpreter to verify the output tomorrow.