71 lines
1.4 KiB
Plaintext
71 lines
1.4 KiB
Plaintext
get "libhdr"
|
|
|
|
// Definitions
|
|
let popcount(n) = n=0 -> 0, (n&1) + popcount(n >> 1)
|
|
let evil(n) = (popcount(n) & 1) = 0
|
|
let odious(n) = (popcount(n) & 1) = 1
|
|
|
|
// The BCPL word size is implementation-dependent,
|
|
// but very unlikely to be big enough to store 3^29.
|
|
// This implements a 48-bit integer using byte strings.
|
|
let move48(dest, src) be
|
|
for i=0 to 5 do dest%i := src%i
|
|
|
|
let set48(dest, n) be
|
|
for i=5 to 0 by -1
|
|
$( dest%i := n & #XFF
|
|
n := n >> 8
|
|
$)
|
|
|
|
let add48(dest, src) be
|
|
$( let temp = ? and carry = 0
|
|
for i=5 to 0 by -1
|
|
$( temp := dest%i + src%i + carry
|
|
carry := temp > #XFF -> 1, 0
|
|
dest%i := temp & #XFF
|
|
$)
|
|
$)
|
|
|
|
let mul3(n) be
|
|
$( let temp = vec 2 // big enough even on a 16-bit machine
|
|
move48(temp, n)
|
|
add48(n, n)
|
|
add48(n, temp)
|
|
$)
|
|
|
|
let popcount48(n) = valof
|
|
$( let total = 0
|
|
for i=0 to 5 do
|
|
total := total + popcount(n%i)
|
|
resultis total
|
|
$)
|
|
|
|
// print the first N numbers
|
|
let printFirst(amt, prec) be
|
|
$( let seen = 0 and n = 0
|
|
until seen >= amt
|
|
$( if prec(n)
|
|
$( writed(n, 3)
|
|
seen := seen + 1
|
|
$)
|
|
n := n + 1
|
|
$)
|
|
wrch('*N')
|
|
$)
|
|
|
|
let start() be
|
|
$( let pow3 = vec 2
|
|
|
|
// print 3^0 to 3^29
|
|
set48(pow3, 1)
|
|
for i = 0 to 29
|
|
$( writed(popcount48(pow3), 3)
|
|
mul3(pow3)
|
|
$)
|
|
wrch('*N')
|
|
|
|
// print the first 30 evil and odious numbers
|
|
printFirst(30, evil)
|
|
printFirst(30, odious)
|
|
$)
|