Skip to content

Instantly share code, notes, and snippets.

@russross
Created January 15, 2017 21:05
Show Gist options
  • Save russross/23f06896acc99a5328cde8a3083e27cf to your computer and use it in GitHub Desktop.
Save russross/23f06896acc99a5328cde8a3083e27cf to your computer and use it in GitHub Desktop.
ARMv6 assembly solution to a math puzzle
@ ARMv6 solution to the puzzle:
@
@ 13 JASONs when added equal FRIDAY.
@ Use only the digits 0 to 9.
@ No leading zeros. Each letter maps to one and
@ only one number.
@
@ JASON + JASON +
@ JASON + JASON + JASON +
@ JASON + JASON + JASON +
@ JASON + JASON + JASON +
@ JASON + JASON = FRIDAY
@
@ Note: this solution assumes each digit can only be used
@ once, i.e., there is a bijection between the digits
@ (0..9) and the letters (j,a,s,o,n,f,r,i,d,y).
@
@ It works by cycling through all possible values for JASON
@ (10,000 up to 99,999) and computing 13 * JASON for each one.
@ It then converts each number to a string and checks the results
@ to see if they match the constraints.
@
@ Compile on a Raspberri Pi running Raspbian using:
@ as -g jasonfriday.s -o jasonfriday.o
@ ld jasonfriday.o -o jasonfriday
@
@ Russ Ross (github user russross), January 15, 2017
.global _start
.equ sys_exit, 1
.equ sys_write, 4
.equ stdout, 1
.data
result: .ascii "jason = "
jasontxt: .space 5
.ascii ", friday = "
fridaytxt: .space 7
.equ resultlen, .-result
.text
_start:
@ r4: jason
@ r5: friday
@ no leading zeros allows, so start
@ with jason = 10000
ldr r4, =10000
b 5f
1:
@ compute friday = 13 * jason
add r5, r4, r4, lsl #1
add r5, r4, r5, lsl #2
@ convert json to text
ldr r0, =jasontxt
mov r1, r4
bl itoa
@ must be exactly 5 digits long
cmp r0, #5
bne 4f
@ convert friday to text
ldr r0, =fridaytxt
mov r1, r5
bl itoa
@ must be exactly 6 digits long
cmp r0, #6
bne 4f
@ 'a' in jason and in friday must match
ldr r0, =jasontxt
ldrb r1, [r0, #1]
ldr r0, =fridaytxt
ldrb r2, [r0, #4]
cmp r1, r2
bne 4f
@ check that each digit is used exactly once
@ set bit #n when we find digit n
@ end result should be the number 1111111111
mov r0, #0
mov r1, #0
mov ip, #1
ldr r2, =jasontxt
2:
ldrb r3, [r2,r1]
sub r3, r3, #'0'
orr r0, r0, ip, lsl r3
add r1, r1, #1
cmp r1, #5
blt 2b
mov r1, #0
ldr r2, =fridaytxt
3:
ldrb r3, [r2,r1]
sub r3, r3, #'0'
orr r0, r0, ip, lsl r3
add r1, r1, #1
cmp r1, #6
blt 3b
ldr r1, =0b1111111111
cmp r0, r1
bne 4f
@ found a solution, so print result
@ append a newline
mov r0, #'\n'
ldr r1, =fridaytxt
strb r0, [r1,#6]
mov r0, #stdout
ldr r1, =result
mov r2, #resultlen
mov r7, #sys_write
svc #0
4:
add r4, r4, #1
5:
ldr r0, =100000
cmp r4, r0
blt 1b
@ exit
mov r0, #0
mov r7, #sys_exit
svc #0
@ itoa(buffer, n) -> number of bytes written
itoa:
.equ div10_magic, 0xcccccccd
push {r4-r6,lr}
@ r0: buffer
@ r1: n
@ r2: length of output
@ r3: division magic number
@ r4: digit
@ r5: new n
ldr r3, =div10_magic
mov r2, #0
1:
@ do a division by 10
umull r4, r5, r3, r1 @ multiply by magic number
mov r5, r5, lsr #3 @ shift: new_n is in r5
add r4, r5, r5, lsl #2 @ compute new_n*5
sub r4, r1, r4, lsl #1 @ remainder = n - new_n*5*2
add r4, r4, #'0' @ convert to digit
strb r4, [r0,r2] @ store in buffer
add r2, r2, #1 @ length++
subs r1, r5, #0 @ n = newn and compare with 0
bgt 1b
@ reverse the string
@ r0: first
@ r1: last
@ r2: length of output
@ r3: firstchar
@ r4: lastchar
add r1, r0, r2
sub r1, r1, #1
bal 3f
2:
ldrb r3, [r0]
ldrb r4, [r1]
strb r3, [r1], #-1
strb r4, [r0], #1
3:
cmp r0, r1
blt 2b
mov r0, r2
pop {r4-r6,pc}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment