8
\$\begingroup\$

Challenge

Given a natural number, output it in the ASCII form of Agrippa's number system.

Description

I like odd alphabets and numeral systems. My favorite numeral system is one given by Heinrich Cornelius Agrippa. It gives a succinct way to write numbers in the range [0,9999], where single digits are written as follows:

Numerals from 1 to 10

Larger numbers less than 10^4 are a combination of single digits, but rotated/horizontally-mirrored on a single central bar as follows:

[0° mirrored, 10's  ] | [0°,            1's  ]
[180°,        1000's] | [180° mirrored, 100's]

Here are a few examples:

Assorted examples

The ASCII equivalents are:

Ones:
  0  1  2  3  4  5  6  7  8  9
  |  |- |_ |\ |/ |~ || |^ |v |]
  |  |  |  |  |  |  |  |  |  |

Tens:
  0  1  2  3  4  5  6  7  8  9
  | -| _| /| \| ~| || ^| v| [|
  |  |  |  |  |  |  |  |  |  |

Hundreds:
  0  1  2  3  4  5  6  7  8  9
  |  |  |  |  |  |  |  |  |  |
  |  |_ |- |/ |\ |~ || |v |^ |]

Thousands:
  0  1  2  3  4  5  6  7  8  9
  |  |  |  |  |  |  |  |  |  |
  | _| -| \| /| ~| || v| ^| [|

 1510:  1511:  1471:  1486:  3421:
 -|     -|-    ^|-    v||    _|-
 _|~    _|~    _|\    -|\    \|\

Numbers larger than 9999 are broken up into sections of 4 digits (with leading zeros added to get a multiple of four) and each is converted. For example:

314159: (0031 4159)
         /|-  ~|]
          |   /|_

Rules

  • Your answer may be a function or full program
  • The input is a positive integer
  • Entries must support inputs over 10^8
  • Each four digit section takes exactly six characters
  • Sections of four are separated by a single space
  • Trailing newline is optional
  • Up to two trailing spaces per line are allowed
  • I will not accept my own answer
  • Score is in bytes, lowest score wins!
\$\endgroup\$
  • \$\begingroup\$ Sorry, but I don't understand any of your examples; they're not even consistent with each other, let alone the graphics. \$\endgroup\$ – Neil Feb 17 '16 at 1:18
  • \$\begingroup\$ @Neil I found that the 6's weren't consistent, but I've fixed them. Is there anything else? Also, what do you mean by "the graphics"? The ASCII art is my interpretation of the graphics, not a direct translation of any kind. \$\endgroup\$ – Michael Klein Feb 17 '16 at 1:23
  • 1
    \$\begingroup\$ I mean i.stack.imgur.com/2BUbM.gif clearly shows that the units is at the top right and the hundreds at the bottom right, but your examples have the hundreds at the top left and the units at the bottom right. \$\endgroup\$ – Neil Feb 17 '16 at 1:28
  • \$\begingroup\$ @Neil Thank you for catching this. Have I missed anything else? \$\endgroup\$ – Michael Klein Feb 17 '16 at 1:36
  • \$\begingroup\$ Your 1486 looks like 2486 to me, but I now agree with the rest. \$\endgroup\$ – Neil Feb 17 '16 at 9:03
3
\$\begingroup\$

Haskell, 310 bytes

  • Defining reverse (as I did: r) is one byte shorter than importing Data.List and using it just once
  • Defining z=0:z and (!)=(!!).(++z) is the shortest way yet that I've found to return 0 for out of bounds
  • I've checked and quickChecked the take4s function, but it still feels like magic to me

Here's the code:

l=lines"    \n--__\n__--\n\\//\\\n/\\\\/\n~~~~\n||||\n^^vv\nvv^^\n][]["
d x|x<1=[]|1<2=mod x 10:d(div x 10)
(&)=(!!)
z=(0::Int):z
(!)=(&).(++z)
t a=[[a!q|q<-[p..p+3]]|p<-[0,4..length a-1]]
g[c,d,b,a]=[[l&b&1,'|',l&a&0,' '],[l&d&3,'|',l&c&2,' ']]
r[]=[]
r(x:y)=r y++[x]
f=unlines.foldl1(zipWith(++)).map g.r.t.d

Less golfed:

import Data.List (reverse)

dict = lines "    \n--__\n__--\n\\//\\\n/\\\\/\n~~~~\n||||\n^^vv\nvv^^\n][]["


-- Note that (digits x) returns the digits of x in little-endian order
digits x  | x < 1     = []
          | otherwise = mod x 10 : digits (div x 10)

-- Note: zeros needs the type signature, because otherwise it won't match [Int] (inferred from (!!))
zeros = (0::Int) : zeros

-- list ! position gives the element at the position, or 0 for out of bounds
(!) = (!!) . (++zeros)

-- This partitions the digits into groups of four, padded right
take4s a = [[a!q | q <-[p..p+3]] | p <- [0,4..length a - 1]]

convertOne[c,d,b,a] = [[dict !! b !! 1, '|', dict !! a !! 0, ' '], [dict !! d !! 3, '|', dict !! c !! 2, ' ']]

f = unlines . foldl1(zipWith (++)) . map convertOne . reverse . take4s . digits

Tests (escape characters removed):

mapM_ print $ lines $ f 1510
-|  
_|~ 

mapM_ print $ lines $ f 1511
-|- 
_|~ 

mapM_ print $ lines $ f 1471
^|- 
_|\ 

mapM_ print $ lines $ f 1486
v|| 
_|\ 

mapM_ print $ lines $ f 3421
_|- 
\|\ 

mapM_ print $ lines $ f 1234567891011121314
_|\ ||^ -|  -|_ -|/ 
 |_ /|~ ^|] _|_ _|/ 

mapM_ print $ lines $ f 1024628340621757567
 |_ _|v  || ^|~ ||^ 
 |_ /|| \|\ -|_ v|~ 
\$\endgroup\$
  • 1
    \$\begingroup\$ I wondered how anyone could answer a challenge this long within a minute of posting. Then I saw you were OP. \$\endgroup\$ – lirtosiast Feb 17 '16 at 1:28
3
\$\begingroup\$

JavaScript (ES6), 180 159 bytes

s=>`000${s}`.slice(-s.length&-4).replace(/..../g,([t,h,d,u])=>(r+=' _-\\/~|v^['[t]+`|${'_-/\\~|v^]'[h]} `,' -_/\\~|^v['[d]+`|${' -_\\/~|^v]'[u]} `),r='')+`\n`+r

Where \n represents a literal newline character.

Edit: Updated for the switch from ,' to |. Saved 14 bytes by using a single replace to do all the work. Saved 3 bytes by using &-4 instead of <<2>>2. Saved 2 bytes by abusing destructuring assignment. Saved 2 bytes by abusing template strings.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.