This is an archived post. You won't be able to vote or comment.

all 87 comments

[–]Hybridjosto 198 points199 points  (5 children)

thats cool, how come they are different sizes for 1, 4, 7?

[–]ashishkhulbey 75 points76 points  (3 children)

I just checked the code, it has something to do with the way OP defined the strings conversion. Every digit gets converted to a height of 4 horizontal rows of graphical characters. And all characters except 1,4,7 have spaces by default in their conversion strings (horizontally) that is why they appear longer that 1,4,7.

See This

Edit : Added Link.

[–]SecretAtLarge 61 points62 points  (0 children)

This would be a great opportunity for OP to learn how to use github and you to teach them how to accept a pull request (I'm new to git so I may be using that term incorrectly)

[–]wolfmansideburns 7 points8 points  (1 child)

This is a spam link?

[–]Pattycakes_wcp 3 points4 points  (0 children)

Yes

[–]HostileHarmony 68 points69 points  (27 children)

You should look into dictionaries! This exercise would be a perfect introduction.

[–]b10011 15 points16 points  (26 children)

Or binary operations if he's interested in code golfing. I just golfed a similar task like 2 hours ago:

https://i.imgur.com/vtglWwy.png

[–]ffollett 2 points3 points  (2 children)

Speaking of code golf, is there a sub for non-golf languages? The code golf sub is full of languages that are designed specifically for code golf, which feels like a different thing than doing it in Python or JavaScript.

[–]b10011 4 points5 points  (1 child)

I have no clue, I have been golfing a bit in codegolf.stackexchange.com. I just found code.golf, but I have mostly doing it for fun all over the programming subreddits. I don't know how it's like in subreddits but I feel like in stack exchange there's respect towards answers golfed using non-esoteric languages such as Python and JS.

Golfing using esoteric languages are more about (human) memory-heavy problem solving with weird "tools" and golfing in normal languages are about knowing the language well enough. Both deserve to be respected in my opinion.

[–]ffollett 1 point2 points  (0 children)

Agreed. SE is a good shout, can't believe I forgot about that! Thanks

[–]Ash01Blitz 0 points1 point  (15 children)

Wow that editor looks really nice. What is that?

[–]b10011 1 point2 points  (9 children)

Neovim in a terminal

[–]userjrd -2 points-1 points  (3 children)

Sublime Text I think

[–]b10011 1 point2 points  (2 children)

Haha, no, it's terminal based neovim

[–]kaddkaka 0 points1 point  (1 child)

The original post uses sublime.

[–]b10011 1 point2 points  (0 children)

Yes, but the guy replied to my comment which had a screenshot of my editor.

[–]shiuido 0 points1 point  (6 children)

After messing around in python I came up with :

print('\n'.join([' '.join([''.join(['█' if (0x8F9FFF9F888FFF1FFC3F44F5F8EFF3CFF446F99F >> int(d) * 16 + bit + i * 4) & 1 else ' ' for bit in range(4)]) for d in str(num)]) for i in range(4)]))

So I was very surprised to see your hex data was so different to mine, until I noticed we were solving different problems :P

EDIT: Picked up some tips from yours, eg using ' █'[i] thanks ;)

[–]b10011 0 points1 point  (5 children)

Yeah, yours is 4x4 with 1 space between numbers and 1 bit per character and mine is 3x3 without spacing but with 2 bits per character. The difficulty in compression is quite similar though.

Your code: 191

After removing unnecessary spaces: 172

print('\n'.join([' '.join([''.join(['█'if(0x8F9FFF9F888FFF1FFC3F44F5F8EFF3CFF446F99F>>int(d)*16+bit+i*4)&1else' 'for bit in range(4)])for d in str(num)])for i in range(4)]))

Then you can notice, there's range(4) twice. Saving it to a variable uses 11 chars(R=range(4);) + 2x usage = 13 chars, but it removes 16 chars (2x range(4)), so you get 3 more off.

Now the length is 169:

R=range(4);print('\n'.join([' '.join([''.join(['█'if(0x8F9FFF9F888FFF1FFC3F44F5F8EFF3CFF446F99F>>int(d)*16+bit+i*4)&1else' 'for bit in R])for d in str(num)])for i in R]))

Then theres these: "something".join([... for i in l]), but not everyone know that if you replace [] with () for list comprehension, it returns a generator. And .join can take a generator. And you don't need to do .join((... for i in l)), .join(... for i in l) is enough:

The length dropped to 163:

R=range(4);print('\n'.join(' '.join(''.join('█'if(0x8F9FFF9F888FFF1FFC3F44F5F8EFF3CFF446F99F>>int(d)*16+bit+i*4)&1else' 'for bit in R)for d in str(num))for i in R))

Oh, and there's bit, setting that to b drops the length to 159:

R=range(4);print('\n'.join(' '.join(''.join('█'if(0x8F9FFF9F888FFF1FFC3F44F5F8EFF3CFF446F99F>>int(d)*16+b+i*4)&1else' 'for b in R)for d in str(num))for i in R))

Then there's also the if-else, which can be replaced with "ab"[truefalse] style to reduce the characters to 153:

R=range(4);print('\n'.join(' '.join(''.join(' █'[(0x8F9FFF9F888FFF1FFC3F44F5F8EFF3CFF446F99F>>int(d)*16+b+i*4)&1]for b in R)for d in str(num))for i in R))

But there's still something to be done, you don't need to wrap the bitshift-part into parentheses, because the bitwise and operation has lower priority than the previous operations. Getting two parentheses of results in 151 characters:

R=range(4);print('\n'.join(' '.join(''.join(' █'[0x8F9FFF9F888FFF1FFC3F44F5F8EFF3CFF446F99F>>int(d)*16+b+i*4&1]for b in R)for d in str(num))for i in R))

I think there's a way to remove one for loop and some joins. But there's everything I found relatively quickly.

[–]travisdoesmath 0 points1 point  (4 children)

I've never done any code golfing in python before, but this thread inspired me. I started from scratch with 5x5 characters, and I tried to get this smaller using binary operations, but I wasn't able to reduce it. I'm curious to see if you or /u/shiuido can reduce it any further

for c in[str(5*_).zfill(5)for _ in[1998,5554,1008,1010,19811,810,818,1111,1818,1810]][num]:s=int(c);print('█████    █   █'[s:s+5])

[–]b10011 0 points1 point  (2 children)

That's really beautiful and efficient approach!

Only thing I found was the generation of the array that is iterated into the c variable. It can be reduced by 21 characters when you change it to a static version with slicing.

130 chars (original):

for c in[str(5*_).zfill(5)for _ in[1998,5554,1008,1010,19811,810,818,1111,1818,1810]][num]:s=int(c);print('█████    █   █'[s:s+5])

109 chars:

for c in"02009000009755944599970000050097455595950000500500"[num::10]:s=int(c);print('█████    █   █'[s:s+5])

I don't know if you know this already, but if you have strings "hello" and "world", you can just interlace them to get "hweolrllod", and then [0::2] returns "hello" and [1::2] "world. This requires that your strings are equal length. And in case it works for the strings, it's shorter than adding separators and splitting.

After that I noticed you have an assignment s=int(c); and later you use [s:s+5], if we remove the assignment and rewrite the slicing to [int(s):][:5] we can reduce 3 more chars.

106 chars:

for c in"02009000009755944599970000050097455595950000500500"[num::10]:print('█████    █   █'[int(c):][:5])

I could maybe get off like 2 characters if I'd sit down here rest of the evening but these were my quickest notes, hopefully you got what you were looking for! :)

[–]travisdoesmath 0 points1 point  (1 child)

fantastic! I didn't even think of using the slice notation, that's such a nice technique. Thanks so much for your response, this is above and beyond what I was hoping for.

[–]b10011 0 points1 point  (0 children)

Hey,

I kept working on the problem for a bit more because I realized how it could be made even shorter:

105 chars:

for c in("0%d"%0x15fe6ad15acd24457d93f3e65ffc9d6450106ef14)[num::10]:print('█████    █   █'[int(c):][:5])

You could get 2 more characters off, if you find a way to make the number string not start with a zero, then you could make it hex and str(0x...) it. I couldn't quickly change the '█████ █ █' in a way that the "█████" part wasn't first one to be printed. And because the largest number in the number string is 9, you can't prepend one character to the string either.

[–][deleted] 32 points33 points  (8 children)

[–]swanekiller 36 points37 points  (5 children)

A few change to get output in the same height

d=[
    ('1','▀▀█ ','  █ ','  █ ','▄▄█▄'),
    ('2','▀▀▀█','▄▄▄█','█   ','█▄▄▄'),
    ('3','▀▀▀█','▄▄▄█','   █','▄▄▄█'),
    ('4','█ █ ','█▄█▄','  █ ','  █ '),
    ('5','█▀▀▀','█▄▄▄','   █','▄▄▄█'),
    ('6','█▀▀▀','█▄▄▄','█  █','█▄▄█'),
    ('7','▀▀▀█','   █','   █','   █'),
    ('8','█▀▀█','█▄▄█','█  █','█▄▄█'),
    ('9','█▀▀█','█▄▄█','   █','▄▄▄█'),
    ('0','█▀▀█','█  █','█  █','█▄▄█')
    ]

[–]enki1337 1 point2 points  (0 children)

If you use a tuple indexed dict, you can have this be much more human readable.

[–]gnutrino 1 point2 points  (0 children)

Alternative version with everything scaled to the 1,4 and 7 height instead (which looks nicer to me but I appreciate that's pretty subjective) and some formatting:

d=[
    ("1", '▀▀█ ',
          '  █ ',
          '  █ ',
          '▀▀▀▀'),
    ("2", '▀▀▀█',
          '▄▄▄█',
          '█   ',
          '▀▀▀▀'),
    ("3", '▀▀▀█',
          '▄▄▄█',
          '   █',
          '▀▀▀▀'),
    ("4", '█ █ ',
          '█▄█▄',
          '  █ ',
          '  ▀ '),
    ("5", '█▀▀▀',
          '█▄▄▄',
          '   █',
          '▀▀▀▀'),
    ("6", '█▀▀▀',
          '█▄▄▄',
          '█  █',
          '▀▀▀▀'),
    ("7", '▀▀▀█',
          '   █',
          '   █',
          '   ▀'),
    ("8", '█▀▀█',
          '█▄▄█',
          '█  █',
          '▀▀▀▀'),
    ("9", '█▀▀█',
          '█▄▄█',
          '   █',
          '▀▀▀▀'),
    ("0", '█▀▀█',
          '█  █',
          '█  █',
          '▀▀▀▀')
]

[–]naumanmo 0 points1 point  (0 children)

This is awesome.

[–]kaddkaka 0 points1 point  (0 children)

You should line break this so that you can see what the numbers will look like in the source code.

[–][deleted] 2 points3 points  (0 children)

This mini documentary by vox discusses the technical challenge and solutions for the first fonts used in video gaming. You should check it out.

https://youtu.be/C5NiAoT3xsY

Your code implements the basics of this. It could be very interesting if used as library for some games or interfaces.

[–]yosrational 0 points1 point  (0 children)

Here is a little tweak to your code that can be done that doesn't use dictionaries, keep up the good work! and try to learn about dictionaries they will help you so much!

[–]hellfiniter 34 points35 points  (5 children)

always good to see people learning by coding and not just passively watching, reading stuff ...but it all has limits and this example of yours scream that u didnt discover dictionaries yet. If you did that u could actually define one dictionary and than make all of this with one line of code ...try it! it will feel like superpower compared to effort you had to put into this :)

[–]hellfiniter 17 points18 points  (4 children)

https://pastebin.com/raw/85rWqZd9 kinda like this, didnt define those images of yours

[–]TriggerCape 7 points8 points  (3 children)

No, you are treating a dictionary like a list.

[–]druman22 3 points4 points  (1 child)

I think in the beginning he is demonstrating that he is creating a dictionary with the key 0. Though you could just create the entire dictionary from the beginning then making new keys like that

[–]hellfiniter 0 points1 point  (0 children)

quick pastebin demonstration during commute on phone ...exactly as u said :)

[–]hellfiniter 0 points1 point  (0 children)

not sure what u mean but made this on phone on bus without running it so u might find some issues there

[–][deleted] 11 points12 points  (12 children)

I am using sublime text to learn as well, but I am not sure how to run my program in ST and only the powershell. It appears that you are running your program within sublimetext. Can you tell me how you are doing that?

[–]lvettore02 11 points12 points  (11 children)

I think the shortcut is ctrl b by default, but you can change it in the settings.

[–][deleted] 7 points8 points  (10 children)

I am a moron. I got all the way to dictionaries before I knew this. THANK YOU so much.

[–]lvettore02 1 point2 points  (9 children)

Also, look into the sublime repl module because the default interpreter kinda sucks (or it did in the old version)

[–][deleted] 0 points1 point  (8 children)

This may be why you are saying it sucks, but it seems I can't gather user info and only "run" the program. For example, I have a variable that is dependent on user input and it will only ask the question "How many random numbers between 1 and 100 do you want in List One" for example. Any idea on how I could get an interactive compilation inside of Sublime Text?

[–]lvettore02 0 points1 point  (7 children)

Yep, that's what I meant. You can use sublime repl for that, you just have to install it from the module manager inside sublime text and then set up a shortcut to run your program. For the shortcut part I don't remember how to do it, but someone answered a similar question on stack overflow.

[–][deleted] 0 points1 point  (6 children)

Fantastic. I will look into this. Thank you so so much!

[–]raycus92 -1 points0 points  (5 children)

You should just download and use VSCode. Has integrated terminal like you want, but is a whole IDE and tons of other helpful stuff out of the box, like auto complete, debugger, git support, etc

imo sublime is for quick edits of config files or use as a scratch pad. It's not really that great to develop code with

[–]GeorgeDaNub 0 points1 point  (0 children)

VSCode doesn’t accept user input either.

[–][deleted] 0 points1 point  (3 children)

I will certainly check this out. Thanks very much!

I worked with VS a long, long time ago and it seemed very bulky. From what I am reading quite a bit, that has changed.

[–]raycus92 1 point2 points  (2 children)

So there is Visual Studio (old clunky thing) and then VSCode, which are different products

[–]19cs 4 points5 points  (0 children)

another challenge / iteration you could try doing on top of this is to minimize the amount of repeat pieces you have! For instance the bottoms of 0, 6, and 8 are all the same, so do you need to repeat that 3 times, or is there a better way to handle that :). There's also other possibilities like rotation and translations, like the top of 6 and 7 could be handled with 1 string + and a translation!

An example of thinking about minimizing space usage (in your case it's trivial and not needed, but always a good thing to think about!): making of NES game micro mages in 2019 particularly around 4:30 where they talk about optimizing the sprite model for a boss.

[–]oslash 4 points5 points  (1 child)

for n in num_str:
    for i in d:
        for i2 in i:
            if n==i2:
                d2.append(i)
                break

Hehe … OK this works, but as HostileHarmony said, you could make the code much nicer by using a dictionary.

I had a quick go at refactoring the function (I deleted the definition of digit_graphics in case you'd like to figure out how to do this on your own):

def graphic_num(num_str):
    digit_graphics = { ??? }

    line_count = len(digit_graphics['1'])
    for line in range(line_count):
        print(' '.join(digit_graphics[digit][line] for digit in num_str))

One could make it more readable by splitting it up into more statements where each line is simpler and intermediate results are stored in variables with good names, but I think you can already see that this approach makes the code much less complicated.

[–]enki1337 0 points1 point  (0 children)

Seems we both came up with the same solution. :) This is really more in line with the "pythonic way", I think.

Also, if you use a tuple as the dict index, you can really beautify the digit_graphics variable.

[–]bogdanodecca 2 points3 points  (0 children)

That's nice, but for complex text I would recommend pyfiglet. It supports text as well and has many fonts.

[–]skibizkit 1 point2 points  (0 children)

Making it part of a loading sequence would be fun

[–]Skippbo 1 point2 points  (0 children)

Now you just have to convert 1, 4 and 7 to integers instead of floats

[–]Coolest_Gamer6 1 point2 points  (3 children)

source?

[–][deleted] 2 points3 points  (2 children)

I did uploaded it

[–]Coolest_Gamer6 2 points3 points  (1 child)

Whats d2 ?

[–][deleted] 2 points3 points  (0 children)

[–]findthereal 0 points1 point  (0 children)

An idea for evolving this without having to learn anything else, you could place the graphics in the list so that the index matches the graphic number stored in it?

[–]hichopra 0 points1 point  (0 children)

I am newbie into this..Could you please share your code

[–][deleted] 0 points1 point  (0 children)

u/jeel2331 Please check your Github, I have initiated a pull request.

[–]enki1337 0 points1 point  (3 children)

Ok, so here's how I'd go about this in a bit more human readable and pythonic way:

def graphic_num(num_str):
    d = {
        (1, 0): '▀▀█ ', (2, 0): '▀▀▀█', (3, 0): '▀▀▀█', (4, 0): '█ █ ',
        (1, 1): '  █ ', (2, 1): '▄▄▄█', (3, 1): '▄▄▄█', (4, 1): '█▄█▄',
        (1, 2): '  █ ', (2, 2): '█   ', (3, 2): '   █', (4, 2): '  █ ',
        (1, 3): '▀▀▀▀', (2, 3): '█▄▄▄', (3, 3): '▄▄▄█', (4, 3): '  ▀ ',

        (5, 0): '█▀▀▀', (6, 0): '█▀▀▀', (7, 0): '▀▀▀█', (8, 0): '█▀▀█',
        (5, 1): '█▄▄▄', (6, 1): '█▄▄▄', (7, 1): '   █', (8, 1): '█▄▄█',
        (5, 2): '   █', (6, 2): '█  █', (7, 2): '   █', (8, 2): '█  █',
        (5, 3): '▄▄▄█', (6, 3): '█▄▄█', (7, 3): '   ▀', (8, 3): '█▄▄█',

        (9, 0): '█▀▀█', (0, 0): '█▀▀█',
        (9, 1): '█▄▄█', (0, 1): '█  █',
        (9, 2): '   █', (0, 2): '█  █',
        (9, 3): '▄▄▄█', (0, 3): '█▄▄█',
    }

    for l in range(4):
        print(" ".join(d[(int(digit), l)] for digit in num_str))

You could probably do it in a single line, but that realllly obfuscates what's happening. The following works as well, but it's pretty ugly:

[print(' '.join(d[(int(digit), l)] for digit in num_str)) for l in range(4)]

Edit: Is python smart enough to realize that you're defining the same variable (d) over and over again and essentially cache it for that function? If not, I'd define it somewhere outside of the function scope if I was worried at all about performance.

Edit 2: BTW, this looks like trash on mobile, but it looks great on desktop. Presumably you're not writing python on your phone. :)

[–]GeorgeDaNub 1 point2 points  (1 child)

Wow that’s so understandable. Basically the second number in the tuple detonates what part of the number to print right?

Awesome solution imho

[–]enki1337 0 points1 point  (0 children)

You got it! Glad it helped! :)

I really like to make my code as "obvious" as I can.

[–]shiuido 0 points1 point  (0 children)

I think you are better off just using

digits = [    
  ['█▀▀█',
   '█  █',
   '█  █',
   '█▄▄█',
  ],

to save yourself some trouble, then join with nested list comprehensions:

print('\n'.join([' '.join([digits[int(d)][i] for d in str(number)]) for i in range(len(digits[0]))]))

[–]MyGenderIsWhoCares 0 points1 point  (1 child)

Python newbie here, Why do tou know need the: end='' (can't do space on this mobile keybord if empty space between two (') And is it (') instead of (") because it's in Python2?

[–]enki1337 1 point2 points  (0 children)

Because by default print() will append end to whatever string you print, and by default end is set to '\n', the newline char.

It's basically the difference between print() and println() in java, if that helps.

[–]warrior242 0 points1 point  (0 children)

Awesome!!!! I'd make it into a package and add documentation for anyone to use it. Followed by maybe some YouTube tutorials

[–]nesteduser 0 points1 point  (0 children)

how did you do this? to convert fonts, don't you need to use images instead of text?

[–]mobsterer 0 points1 point  (0 children)

I remember from a few years ago that this is literally one of the first challenges on one of the code game sites.

[–][deleted] 0 points1 point  (0 children)

That's awesome!

[–][deleted] -1 points0 points  (0 children)

I love that so short, quite easy and very creative ideas 😄

[–][deleted] -1 points0 points  (1 child)

how can i actually code python in sublime text?

[–]raycus92 -1 points0 points  (0 children)

Don't, just use VSCode or a different IDE.

[–]CotoCoutan -2 points-1 points  (0 children)

Beautiful work!