107
\$\begingroup\$

Write a program that takes in a non-empty string of the digits 0 through 9 and prints how they would be shown on a seven-segment display using slashes (/, \).

These are the precise digit shapes:

/\  
\ \
 \/

 \
  \


/\
 /
 \/

/\
 /\
  /

 \
\/\

/
\/\
  /

/
\/\
 \/

/\
  \

/\
\/\
 \/

/\
\/\
  /

When one digit occurs after another, they are chained diagonally up and to the right, with a diagonal space in between. So, for example, 203 would become this:

    /\
     /\
  /\  /
  \ \
/\ \/
 / 
 \/

Note that the 1 character takes up the same amount of space as the others. The two lines of the 1 are on the right side of the display, not the left.

So 159114 would become this:

           \
          \/\
         \
          \
       \
        \
    /\
    \/\
  /   /
  \/\
 \  /
  \

There may be any amount and combination of leading/trailing newlines or spaces in the output as long as the digits are in the correct position with respect to one another.

So for 159114, this would also be valid:



          \        
         \/\     
        \
         \
      \    
       \          
   /\     
   \/\
 /   /
 \/\         
\  /
 \    


Take input from stdin or the command line, or write a function that takes in a string. Print the result to stdout or you can return it as a string if you write a function.

Any non-empty string of the digits 0 through 9 should work, including single digits strings (e.g. 8) and strings with leading zeros (e.g. in 007, the zeros do need to be printed).

The shortest code in bytes wins.

\$\endgroup\$
11
  • 42
    \$\begingroup\$ Totally offtopic: This looks awesome! \$\endgroup\$
    – Martijn
    Commented Jun 9, 2015 at 9:08
  • 4
    \$\begingroup\$ This is really really cool. However, I'm not sure kolmogorov-complexity is appropriate for this question - I thought that that required a constant output? \$\endgroup\$
    – alyx-brett
    Commented Jun 9, 2015 at 11:36
  • 1
    \$\begingroup\$ @alexander-brett iirc that was the original intention, however, more recently it's been used for problems where the majority of the code is probably going to be hardcoding. \$\endgroup\$ Commented Jun 9, 2015 at 13:45
  • \$\begingroup\$ This made me go like... WOW! just WOW! \$\endgroup\$ Commented Jun 9, 2015 at 21:47
  • \$\begingroup\$ Question: Do we need to handle empty strings or strings with non-digit characters? \$\endgroup\$
    – fvla
    Commented Jun 10, 2015 at 18:57

15 Answers 15

25
\$\begingroup\$

Python 3, 189 183 174 bytes

s="a%sa"%input()
while s[1:]:b,a,c,d,e,f,g=[c*(ord(n)>>int(s[~(n>"Ͱ")],16)&1)or" "for c,n in zip("\/"*4,"ΟϭŅͭͱͼϻ")];S=len(s)*"  ";print(S+a+b,c+d+"\n"+S+e+f+g);*s,_=s

The compression looks okay to me, but I'm having trouble coming up with a good way of ditching the seven variables...

Thankfully the spec is fairly relaxed on whitespace rules, because there's a lot of leading/trailing whitespace.

Expanded:

s="a%sa"%input()
while s[1:]:
  b,a,c,d,e,f,g=[c*(ord(n)>>int(s[~(n>"Ͱ")],16)&1)or" "
                 for c,n in zip("\/"*4,"ΟϭŅͭͱͼϻ")]
  S=len(s)*"  "
  print(S+a+b,c+d+"\n"+S+e+f+g)
  *s,_=s

Explanation

The segment positions represented by the variables are:

    ab               /\
    efg               /\
  ab cd            /\  /
  efg              \ \
ab cd            /\ \/
efg               /
 cd               \/

Each segment is encoded by a single 2-byte Unicode character. For example, ϻ encodes g's segment like so:

bin(ord("ϻ")) = bin(1019) = "0b1111111011"
                               ^^^^^^^^^^
                               9876543210

Indeed, 2 is the only digit to not use the bottom-right segment of a seven-segment display.

\$\endgroup\$
19
\$\begingroup\$

C, 1098 345 323 319 bytes

First Second Third attempt. Finally decided to ditch the screen buffer to save a few bytes. This program takes a parameter of digits and prints the digits in 7-segment format.

First time participant. Just for fun. Be gentle.

a[]={100489,2056,98569,67849,2440,67969,100737,2057,100745,67977},i,j,k,n,m;char*c=" /\\";
#define f(q,r) for(q=0;q<(r);q++)
#define P(w) putchar(w)
#define Q(d,i,j) P(c[a[v[1][d]-48]>>(i*3+j)*2&3])
main(w,char**v){f(i,n=strlen(v[1]))f(k,(m=n-i-1)?2:3){f(j,m*2)P(32);f(w,3)Q(m,k,w);if(!k&&i)f(w,2)Q(m+1,2,w+1);P(10);}}

Expanded, warning free:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int a[]={100489,2056,98569,67849,2440,67969,100737,2057,100745,67977};
char *c=" /\\";
#define f(q,r) for(q=0;q<(r);q++)
#define P(w) putchar(w)
#define Q(d,i,j) P(c[a[v[1][d]-48]>>(i*3+j)*2&3])
int main(int w, char **v)
{
    int i,j,k,n,m;
    f(i,n=strlen(v[1])) {
        m=n-i-1;
        f(k,m?2:3) {
            f(j,m*2) P(32);
            f(w,3) Q(m,k,w);
            if (!k&&i) f(w,2) Q(m+1,2,w+1);
            P(10);
        }
    }
}
\$\endgroup\$
10
  • \$\begingroup\$ Fastest gun in the west. I'm compressing mine now. \$\endgroup\$ Commented Jun 9, 2015 at 1:11
  • 15
    \$\begingroup\$ Hey! Welcome to Code Golf. The purpose of this challenge is to make your code as short as possible, so you should make some optimizations in regards to removing spaces, shorting statements, etc, and then report your byte count at the top of your post with the language. Great first post though! Just for reference, your initial post is 1,098 bytes long. \$\endgroup\$
    – Kade
    Commented Jun 9, 2015 at 1:17
  • \$\begingroup\$ Thanks. Just added the language and byte count. My original even has comments and Usage. :) \$\endgroup\$
    – some user
    Commented Jun 9, 2015 at 5:16
  • \$\begingroup\$ Tip: Change all variable names to single characters. Also, you use ` for (i = 0; i < digits` alot, perhaps replace it with a macro? \$\endgroup\$
    – Sarima
    Commented Jun 9, 2015 at 7:43
  • \$\begingroup\$ Good job here. To make your score more competitive, you could take a look at our tips for golfing in C. \$\endgroup\$
    – Alex A.
    Commented Jun 9, 2015 at 14:45
14
\$\begingroup\$

JavaScript, 192 178 167 162 bytes

f=x=>{n=b="\n";for(k in x)for(i=0;i<8;)b+=("î\xA0Öô¸|~àþü".charCodeAt(x[k])>>i++&1?i%2?"/":"\\":" ")+(i%3?"":n+"  ".repeat(k));return b.split(n).reverse().join(n)}

Usage: f("1337"); will return

      /\
        \
    /\   
     /\
  /\  /
   /\
 \  /
  \
   

It uses features of ES6 and may have some implementation dependent behavior due to omission of semicolons and parentheses and such, but it works in Firefox.

Expanded:

f=x=>
{
    n = b = "\n";

    for (k in x)
        for (i=0; i<8;)
            b += ("î\xA0Öô¸|~àþü".charCodeAt(x[k]) >> i++ & 1? i%2? "/" : "\\" : " ") + (i%3? "" : n+"  ".repeat(k));

    return b.split(n).reverse().join(n)
}

Explanation:

l is an array containing 10 single byte characters which correspond to the shape of each digit. For example, the digit 0 is represented by the character î:

/\        11
\ \  -->  101  --> 11 101 110 = î
 \/       011

The input characters are used as keys to the array holding their shape representing counterparts, which get read bit by bit.

\$\endgroup\$
8
  • 2
    \$\begingroup\$ Are ==0 and ==1 indeed necessary before ?. Aren't int considered as boolean in js? @Regret \$\endgroup\$ Commented Jun 9, 2015 at 17:22
  • 1
    \$\begingroup\$ @Regret : "w\x05k/\x1D>~\x07\x7F?" with each character bitwise reversed becomes "\xee\xa0\xd6\xf4\xb8|~\xe0\xfe\xfc" , each of these are printable. This gives 8 more bytes. Although, not enough... \$\endgroup\$ Commented Jun 9, 2015 at 17:45
  • 1
    \$\begingroup\$ You could shave 2 bytes off by removing the parenthesis in f=(x)=>{} -- they're not needed with only one argument. \$\endgroup\$
    – Scimonster
    Commented Jun 9, 2015 at 18:06
  • \$\begingroup\$ You are absolutely right, @Alexey. I will change that. \$\endgroup\$
    – Regret
    Commented Jun 9, 2015 at 22:26
  • \$\begingroup\$ Does it work? I get 6 more rows with spurious characters. \$\endgroup\$
    – edc65
    Commented Jun 11, 2015 at 5:43
10
\$\begingroup\$

Perl - 103 Bytes

#!perl -n
print$i+$%2?U^(u,$i--%2?v9:z)[$i<4+$%2&vec$_,4*$-3-$i,1]:$/.!($i=$--)
while$+=2*y/0-9/wPkz\\>?p~/

The above contains 6 unprintable characters (the source can be downloaded at Ideone), and is equivalent to the following:

#!perl -n
print$i+$^F%2?U^(u,$i--%2?v9:z)[$i<4+$^F%2&vec$_,4*$^F-3-$i,1]:$/.!($i=$^F--)
while$^F+=2*y/0-9/wPkz\\>?p\177~/

Each ^F may be replaced by a literal character 6 (ACK), and \177 replaced by character 127 (DEL).

The shebang is counted as 1, the second newline is uncessary. Input is taken from stdin.


Sample Usage

$ echo 0123 | perl seven-slash.pl

      /\
       /\
    /\  /
     /
   \ \/
    \
/\
\ \
 \/

$ echo 456789 | perl seven-slash.pl

          /\
          \/\
        /\  /
        \/\
      /\ \/
        \
    /
    \/\
  /  \/
  \/\
 \  /
\/\

Explanation

Output is generated one byte at a time. Each character is transliterated, and this is then interpreted as a bit array using vec. The bits are stored in the following way:

   /\           56 
   \/\          234
 /\ \/   ->   56 01
 \/\          234 
  \/           01

Output alternates between 3 and 5 slashes, so that bits 56 spills over into 01 of the next digit. Bit 7 is not used.

\$\endgroup\$
9
\$\begingroup\$

CJam, 77 71 70 69 63 62 bytes

r_,5*_Sa*a*\{~"÷Ðëúܾ¿ðÿþ"=i2bS"\/"4*W<+.*3/..e>2fm>2m>}/Wf%N*

All characters are printable, so copy and paste should work just fine.

Try it online in the CJam interpreter.

Idea

We start by examining the number of digits n in the input and pushing a square of spaces big enough to cover the output. In the implementation, this square will be encoded as a two-dimensional array of one-character strings.

A square of length 2n+1 would be just right (i.e., no surrounding whitespace) for a straightforward implementation, but we'll use one of length 5n to save a couple of bytes. Thankfully, surrounding whitespace is allowed.

If we reverse the lines of the seven slash representation of 8, we obtain the following:

 \/
\/\
/\

The representation of all digits can be encoded as an 8-bit integer, where the ith bit is 0 iff the ith character should get replaced with a space. For the digits 0 to 9, the resulting integers are

247 208 235 250 220 190 191 240 255 254

which correspond to the following ISO-8559-1 characters:

÷Ðëúܾ¿ðÿþ

For each digit in the input, after selecting the corresponding 8-bit integer, we repeat the ith character of the representation of 8 exactly ai times, where ai is the ith bit of the integer. This pushes an array of strings of either one or zero characters. By dividing this array into chunks of length 3, we obtain an array where each element corresponds to a line of the representation.

Now, we compute the vectorized maximum of the strings that represent the square and the strings that represent the digit. The strings / and \ are bigger than the string  , so they will replace the spaces in the square. The empty string, however, is smaller than the string  , so empty strings in the digit representation will preserve the spaces in the square.

We now rotate the rows and columns by two units to place the following digit representation in the proper part of the square and repeat the process for the remaining digits in the input.

Finally, we reverse each row and insert a linefeed between the individual rows.

Code

r_,      e# Read a token from STDIN and push the length of a copy.
5*_      e# Multiply the length by 5 and push a copy.
Sa*      e# Repeat the array [" "] that many times.
a*       e# Repeat the array [[" " ... " "]] that many times.
\{       e# For each character C in the input:
  ~      e#   Push eval(C), i.e., the digit the character represents.

  "÷Ðëúܾ¿ðÿþ"

         e#   Push the encodings of all 10 seven slash representations.

  =      e#   Select the proper one.
  i2b    e#   Push the resulting characters code point in base 2, i.e., its bits.
  S      e#   Push " ".
  "\/"4* e#   Push "\/\/\/\/".
  +W<    e#   Concatenate and eliminate the last character.
  .*     e#   Vectorized repetition.

         e#   For the digit 5, e.g., we have [1 0 1 1 1 1 1 0] and  " \/\/\/\" on
         e#   the stack, so .* yields [" " "" "/" "\" "/" "\" "/" ""].

  3/     e#   Divide the representation into chunks of length 3, i.e., its lines.
  ..e>   e#   Compute the twofold vectorized maximum, as explained above.
  2fm>   e#   Rotate each line to characters to the right.
  2m>    e#   Rotate the lines two units down.
}/
Wf%      e# Reverse each line.
N*       e# Place linefeeds between them.

The last rotations would mess up the output if the square's side length was smaller than 2n+3. Since 5n ≥ 2n+3 for all positive integers n, the square is big enough to prevent this.

\$\endgroup\$
5
  • \$\begingroup\$ Would it be sensible to post here a base64 version of your code? \$\endgroup\$
    – TRiG
    Commented Jun 11, 2015 at 13:27
  • 1
    \$\begingroup\$ +1, but to be honest, I was hoping CJam et al. would sit this one out :p \$\endgroup\$
    – primo
    Commented Jun 12, 2015 at 5:32
  • \$\begingroup\$ @primo: I feel the same way about Pyth and math questions. :P I'm a little bit late to the party because I got nerd-sniped by Rearranging Words. It wasn't until your edit this morning that I remembered this question. \$\endgroup\$
    – Dennis
    Commented Jun 12, 2015 at 5:43
  • \$\begingroup\$ @Dennis challenges seem to go by a lot faster than they used to. I'm still working on one from two weeks ago :p \$\endgroup\$
    – primo
    Commented Jun 12, 2015 at 7:01
  • 1
    \$\begingroup\$ I always look for CJam first with the expectation that it will have the lowest byte count. I have yet to be disappointed. \$\endgroup\$ Commented Jun 12, 2015 at 13:46
9
\$\begingroup\$

C#, 360 355 331 bytes

Hi there, first attempt at code-golf. Hope this doesn't score too badly for a C#-entry.

string p(string n){var l=new string[n.Length*2+1];var i=l.Length-1;for(;i>0;){var x=@"/\\ \\/ \  \  /\ / \//\ /\ / \\/\  / \/\ // \/\\//\  \  /\\/\\//\\/\ /".Substring((n[0]-48)*7,7);for(var j=i-3;j>=0;){l[j--]+="  ";}l[i--]+=" "+x[5]+x[6];l[i--]+=""+x[2]+x[3]+x[4];l[i]+=""+x[0]+x[1];n=n.Remove(0, 1);}return string.Join("\n",l);}

Usage: p("159114"); will return

          \
         \/\
        \
         \
      \
       \
   /\
   \/\
 /   /
 \/\
\  /
 \

Expanded:

string p(string n)
    {
        var l = new string[n.Length * 2 + 1];
        var i = l.Length - 1;
        for (; i > 0; )
        {
            var x = @"/\\ \\/ \  \  /\ / \//\ /\ / \\/\  / \/\ // \/\\//\  \  /\\/\\//\\/\ /".Substring((n[0] - 48) * 7, 7);

            for (var j = i - 3; j >= 0; )
            {
                l[j--] += "  ";
            }
            l[i--] += " " + x[5] + x[6];
            l[i--] += "" + x[2] + x[3] + x[4];
            l[i] += "" + x[0] + x[1];

            n = n.Remove(0, 1);
        }

        return string.Join("\n", l);
    }
\$\endgroup\$
3
  • 1
    \$\begingroup\$ I know it's been almost three years, but you can golf 30 bytes: Try it online. 301 bytes. Nice answer though, +1 from me. \$\endgroup\$ Commented May 4, 2018 at 13:00
  • \$\begingroup\$ Cool. Feel free to post it as your own answer then :) \$\endgroup\$
    – Shion
    Commented May 4, 2018 at 14:10
  • 1
    \$\begingroup\$ No, it's your code. I just shortened a bit by removing the for-loop brackets and combining variables. And changing string s(string n) to n=> by using a lambda. Ah well, you can just leave it like this if you prefer. :) I did create a port to Java crediting you however. ;) \$\endgroup\$ Commented May 4, 2018 at 14:17
4
\$\begingroup\$

python 2, 317 298 278 273.15

def f(s):
    r=range;n=len(s)*2;l=[[' ']*-~n for x in r(-~n)]
    for x in r(0,n,2):
        for i,[d,y,c]in enumerate(zip('0112012','1021012',r'\\\\///')):l[n-2-x+int(y)][x+int(d)]=[' ',c][('%7s'%(bin(ord('}(7/jO_,\x7fo'[map(int,s)[x/2]])))[2:])[i]=='1']
    for x in l:print''.join(x)

I considered 4-spaces as tabs while counting.
Uncompressed and readable:

def f(s):
    r=['1111101','0101000','0110111','0101111','1101010','1001111','1011111','0101100','1111111','1101111']
    ''.join(map(lambda x:chr(eval('0b'+x)),r))
    n=len(s)*2
    l=[[' ']*(n+1) for x in xrange(n+1)]
    shifts=[(0,1,'\\'),(1,0,'\\'),(1,2,'\\'),(2,1,'\\'),(0,0,'/'),(1,1,'/'),(2,2,'/')]
    for x in xrange(0,n,2):
        y=n-2-x
        for i,[dx,dy,c] in enumerate(shifts):
            l[y+dy][x+dx]=c if r[map(int,s)[x/2]][i]=='1' else ' '
    return '\n'.join(''.join(x) for x in l)
\$\endgroup\$
7
  • \$\begingroup\$ Hey! Great answer, but you can make a few changes to get it even shorter. Changing l[y+dy][x+dx]=c if r[map(int,s)[x/2]][i]=='1' else ' ' to l[y+dy][x+dx]=[' ',c][r[map(int,s)[x/2]][i]=='1'] saves 5 bytes, changing return '\n'.join(''.join(x) for x in l) to print'\n'.join(''.join(x)for x in l) saves 3 bytes, plus a few more changes. Here's a link to a Gist where I got the byte count down to 440 from 508. \$\endgroup\$
    – Kade
    Commented Jun 9, 2015 at 1:40
  • 6
    \$\begingroup\$ Kelvin would have been very pleased with that score. \$\endgroup\$ Commented Jun 9, 2015 at 6:26
  • 3
    \$\begingroup\$ Your answer is actually 272 bytes, but you can save one more because a space is shorter than a tab. See here. How could you have 273.15 bytes anyway? \$\endgroup\$
    – mbomb007
    Commented Jun 9, 2015 at 18:56
  • 1
    \$\begingroup\$ 273.15 bytes means @AlexeyBurdin figured out analog computing on a digital platform. Why in the world did you publish it here, instead of in Science? ;-) \$\endgroup\$
    – hBy2Py
    Commented Jun 11, 2015 at 15:30
  • 1
    \$\begingroup\$ This means only that the solution is frozen at absolute zero, i.e. I don't want to focus on a thing that has already lost. :) \$\endgroup\$ Commented Jun 11, 2015 at 15:36
4
\$\begingroup\$

KDB(Q), 172 136 bytes

{d:(9#1 2 0 2)*/:-9#'0b vs'427 136 403 409 184 313 315 392 443 441;
 -1" /\\"{m+(c,/:y),c:(count[m:0 0,x,\:0 0]-3)#0}/[3 3#/:d"J"$'(),x];}

Explanation

1) Create d map with all the digits' shapes.

2) Pad the matrix with extra zeros and add them together. i.e. "01"

0           0 0 0 2 0   
0           0 0 0 0 2
1 2 0 0 0 + 0 0 0 0 0
2 0 2 0 0   0
0 2 1 0 0   0

3) Use the index to map " /\" and print with -1.

Test

q){d:(9#1 2 0 2)*/:-9#'0b vs'427 136 403 409 184 313 315 392 443 441;-1" /\\"{m+(c,/:y),c:(count[m:0 0,x,\:0 0]-3)#0}/[3 3#/:d"J"$'(),x];}"0123456789"
                  /\
                  \/\
                /\  /
                \/\
              /\ \/
                \
            /
            \/\
          /  \/
          \/\
         \  /
        \/\
      /\
       /\
    /\  /
     /
   \ \/
    \
/\
\ \
 \/

I'm sure this can be shorter!!

Thanks @h.j.k.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ The only reduction I spotted is to replace 1 2 0 2 1 2 0 2 1 with (9#1 2 0 2) (-6). \$\endgroup\$
    – h.j.k.
    Commented Jun 11, 2015 at 9:28
  • 1
    \$\begingroup\$ Oh, and replacing enlist with 1# works, so that's another -5. \$\endgroup\$
    – h.j.k.
    Commented Jun 11, 2015 at 9:34
  • 1
    \$\begingroup\$ you are a star! I'll update! but cant replace the enlist though because count[a 0]#0 is not atom :( \$\endgroup\$ Commented Jun 11, 2015 at 9:37
  • \$\begingroup\$ ah strange it worked for me though... must be a quirk. ;) \$\endgroup\$
    – h.j.k.
    Commented Jun 11, 2015 at 9:44
  • 1
    \$\begingroup\$ actually, list plus atom will extend the atom to the correct length anyway! you reminded me such mechanism! :D \$\endgroup\$ Commented Jun 11, 2015 at 9:44
4
\$\begingroup\$

Brainfuck - 719 bytes

For historical context only, credits to Daniel B Cristofani. I'm not exactly sure when this was created, but it is available from the Internet Archive as early as May 9th, 2003.

The output for 9 is different than in the problem description.

>>>>+>+++>+++>>>>>+++[
  >,+>++++[>++++<-]>[<<[-[->]]>[<]>-]<<[
    >+>+>>+>+[<<<<]<+>>[+<]<[>]>+[[>>>]>>+[<<<<]>-]+<+>>>-[
      <<+[>]>>+<<<+<+<--------[
        <<-<<+[>]>+<<-<<-[
          <<<+<-[>>]<-<-<<<-<----[
            <<<->>>>+<-[
              <<<+[>]>+<<+<-<-[
                <<+<-<+[>>]<+<<<<+<-[
                  <<-[>]>>-<<<-<-<-[
                    <<<+<-[>>]<+<<<+<+<-[
                      <<<<+[>]<-<<-[
                        <<+[>]>>-<<<<-<-[
                          >>>>>+<-<<<+<-[
                            >>+<<-[
                              <<-<-[>]>+<<-<-<-[
                                <<+<+[>]<+<+<-[
                                  >>-<-<-[
                                    <<-[>]<+<++++[<-------->-]++<[
                                      <<+[>]>>-<-<<<<-[
                                        <<-<<->>>>-[
                                          <<<<+[>]>+<<<<-[
                                            <<+<<-[>>]<+<<<<<-[
                                              >>>>-<<<-<-
  ]]]]]]]]]]]]]]]]]]]]]]>[>[[[<<<<]>+>>[>>>>>]<-]<]>>>+>>>>>>>+>]<
]<[-]<<<<<<<++<+++<+++[
  [>]>>>>>>++++++++[<<++++>++++++>-]<-<<[-[<+>>.<-]]<<<<[
    -[-[>+<-]>]>>>>>[.[>]]<<[<+>-]>>>[<<++[<+>--]>>-]
    <<[->+<[<++>-]]<<<[<+>-]<<<<
  ]>>+>>>--[<+>---]<.>>[[-]<<]<
]
[Enter a number using ()-./0123456789abcdef and space, and hit return.
Daniel B Cristofani (cristofdathevanetdotcom)
http://www.hevanet.com/cristofd/brainfuck/]
\$\endgroup\$
1
  • 2
    \$\begingroup\$ I probably wrote it in 2002. The Internet Archive says Panu Kalliokoski added it to his brainfuck repository in August 2002. As for the 9, I think I used the patterns from the second edition of Microprocessors and Interfacing, page 4. \$\endgroup\$ Commented Jul 18, 2015 at 4:04
2
\$\begingroup\$

Pip, 122 + 1 = 123 bytes

Uses the -n flag. Takes input via command-line argument.

l:$.(J"\/ "@^(A_TB3M"⮐䫶ヷ㄃䓳ⴷⴥㅕ⬿⭑")@_.2<>2Ma)z:2*#ap:sXz+2RLz+2Fi,5Fj,z{c:[4-ii]//2+j(pc@0c@1):(lij)}RVp

The characters in the UTF-8 string have the following code points: 11152, 19190, 12535, 12547, 17651, 11575, 11557, 12629, 11071, 11089.

Slightly ungolfed:

t:[120022001 222022202 122012021 122012201 220012202 120212201 120212001 122022202 120012001 120012201]
l:$.({J"\/ "@^[email protected]<>2}Ma)
z:2*#a+2
p:sXzRLz
Fi,5
 Fj,2*#a {
  x:i//2+j
  y:(4-i)//2+j
  p@y@x:l@i@j
 }
P RVp

The basic strategy is to find each number's constituent characters and then skew them appropriately. For example, for 8, we want this (spaces represented by dots):

/.
\\
/.
\\
/.

which will turn into this:

 .  
/\. 
\/\.
 \/ 

The nice feature of this strategy is that multiple pre-skewed numbers can simply be concatenated side by side.

Now, we can encode /.\\/.\\/. in base 3 as 1200120012. Then we can convert this to decimal and treat it as a UTF-8 code point.

The expression J"\/ "@^(A_TB3M"⮐䫶ヷ㄃䓳ⴷⴥㅕ⬿⭑")@_.2<>2Ma gets the pre-skewed data by the following process:

                            Ma   Map this lambda function to each character in input:
        (A_TB3M"...")            Create list of the code points of each character in UTF-8
                                   string, converted to base 3
                     @_          Index into that list using the input character
                       .2        Concatenate 2 to the end of the base-3 value (all of the
                                   pre-skewed number grids end in 2, i.e. space)
       ^                         Split the number into a list of its digits
 "\/ "@                          Index into this string with those digits, giving a list
                                   of slashes & spaces
J                                Join the list together into a string
                         <>2     Group string two characters at a time

Once we have concatenated these strings side-by-side using $., we then create a grid of spaces (2*n+2 square), loop through the pre-skewed grid, and replace the corresponding spaces in the post-skewed grid with the appropriate characters. To see it happening, one can modify the code to print each stage and pause for user input:

Algorithm in process

The grid is actually built upside down, because that seemed to make the math easier.

I'm sure there's better algorithms to use. But I wanted to come up with my own idea rather than copying somebody else's.

More on Pip

\$\endgroup\$
1
\$\begingroup\$

Perl, 270 bytes

I really shouldn't have wasted my time on this.

$e="\\";$g=" ";$_=reverse<>;$l=length;push@a,(119,18,107,91,30,93,125,19,127,95)[$1]while/(.)/g;for($i=0;$i<=$l;$i++){$j=2*($l-$i);$b=$a[$i];$c=$i&&$a[$i-1];print" "x$j,$b&1?"/":$g,$b&2?$e:$g,$g,$c&32?$e:$g,$c&64?"/":$g,"
"," "x$j,$b&4?$e:$g,$b&8?"/":$g,$b&16?$e:$g,"
"}
\$\endgroup\$
1
  • \$\begingroup\$ replace [$1]while/(.)/g with [$_]for/./g to save 4 bytes. replace for($i=0;$i<=$l;$i++) with for$i(0..$l) to save 9 bytes. \$\endgroup\$
    – hobbs
    Commented Jul 9, 2015 at 1:18
1
\$\begingroup\$

JavaScript (ES6), 191 206

Run snippet in Firefox to test.

F=m=>(
  a='    \\/  /\\/\\ /  /\\  \\\\ \\'.match(/.../g),
  o=f='',r=' ',
  [for(d of m)(
    n=1e3+'¯B\x91ÿ$ê\x86A\x87ë'.charCodeAt(d)+'', // here there are 3 valid characters tha the evil stackoverflow editor just erase off, so I had to put them as hex escape
    o='\n'+f+' '+a[n[2]]+'\n'+r+a[n[1]]+o,
    r=f+a[n[3]],
    f+='  ')],
  r+o
)


//TEST

go=_=>O.innerHTML =(v=I.value)+'\n'+F(v)

go()
<input id=I value='0123456789'><button onclick='go()'>-></button>
<pre id=O></pre>

\$\endgroup\$
1
\$\begingroup\$

Java 8, 341 bytes

n->{int i=n.length*2,j=i+1,k=0,t;String l[]=new String[j],x;for(;j-->0;l[j]="");for(;i>0;l[i--]+=" "+x.substring(5,7),l[i--]+=x.substring(2,5),l[i]+=x.substring(0,2))for(x="/~~ ~~/ ~  ~  /~ / ~//~ /~ / ~~/~  / ~/~ // ~/~~//~  ~  /~~/~~//~~/~ /".replace('~','\\').substring(t=(n[k++]-48)*7,t+7),j=i-2;j-->0;)l[j]+="  ";return"".join("\n",l);}

Port of @Shion's C# .NET answer, so make sure to upvote him as well!

Try it online.

Explanation:

n->{                       // Method with character-array parameter and String return-type
  int i=n.length*2,        //  Two times the length of the input array
      j=i+1,               //  Index integer, starting at `i+1`
      k=0,t;               //  Temp integers
  String l[]=new String[j],//  String-array for the rows, default filled with `null`
         x;                //  Temp-String
  for(;j-->0;l[j]="");     //  Replace all `null` with empty Strings
  for(;i>0                 //  Loop `i` downwards in the range [`n.length*2`, 0)
      ;                    //   After every iteration:
       l[i--]+=            //    Append the row at index `i` with:
                           //    (and decrease `i` by 1 afterwards with `i--`)
         " "               //     A space
         +x.substring(5,7),//     And the 6th and 7th characters of temp-String `x`
       l[i--]+=            //    Append the row at index `i` with:
                           //    (and decrease `i` by 1 afterwards with `i--`)
         x.substring(2,5), //     The 3rd, 4th and 5th characters of temp-String `x`
       l[i]+=              //    Append the row at index `i` with:
         x.substring(0,2)) //     The 1st and 2nd characters of the temp-String `x`
    for(x="/~~ ~~/ ~  ~  /~ / ~//~ /~ / ~~/~  / ~/~ // ~/~~//~  ~  /~~/~~//~~/~ /".replace('~','\\')
                           //   String containing all digit-parts
          .substring(t=(n[k++]-48)*7,t+7),
                           //   and take the substring of 7 characters at index
                           //   `n[k]` as integer multiplied by 7
        j=i-2;j-->0;)      //   Inner loop `j` in the range (`i`-2, 0]
      l[j]+="  ";          //    And append the rows at index `j` with two spaces
  return"".join("\n",l);}  //  Return the rows delimited with new-lines
\$\endgroup\$
1
\$\begingroup\$

JavaScript (Node.js),  149  146 bytes

Contains a few unprintable characters which are escaped in the code below.

s=>(g=([d,...s],p='',q=p)=>d?g(s,p+q,88)+(p+=q?`10 65
${p}234
`:865).replace(/\d/g,n=>'\\/ '[Buffer("w\x11k;\x1d>~\x13\x7f?")[n>4?s[0]:d]>>n&1?n&1:2]):s)(0+s)

Try it online!

How?

This recursively builds the following pattern (here with 4 digits):

88888810 65
888888234
888810 65
8888234
8810 65
88234
10 65
234
865

Where:

  • \$8\$ is a padding character
  • other even digits are replaced with either \ or a space
  • odd digits are replaced with either / or a space

Leading to:

______/\ \/
______\/\
____/\ \/
____\/\
__/\ \/
__\/\
/\ \/
\/\
_\/
\$\endgroup\$
0
\$\begingroup\$

JavaScript (V8), 188 bytes

f=x=>{o='';t='  ';p=`
`
for(k in x){q=r=s=''
for(i=0;i<7;i++){b="wƒk[ƞ]}Ɠÿ_".charCodeAt(x[k])>>i&1?i%3?'\\':'/':' '
i<2?q+=b:i>4?s+=b:r+=b}o=r+p+t+' '+s+p+o
t=q
p+='  '}return p+t+p+o}

Try it online!

Inspired by @Regret's answer, I attempted to do this by building the string from the bottom up thus avoiding the split().reverse().join() code.

However, this requires a lot of extra code to handle the temporary storage.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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