For an integer n that satisfies n > 0, write its value as a right-descending path based on its binary representation.
Rules
- The first (most significant) set bit is always in the top-left corner.
- When the next bit is set (a
1), draw a character ("filled") on the next line in the same column as the previous character drawn. Try to use spaces ("empty") to fill, but any character will do as long as it's always the same. - When the next bit is unset (a
0), draw a character ("filled") on the same line immediately to the the right of the previous character drawn. - Your code must support numbers with at least 20 significant bits.
- Write a full program, a function, a lambda, etc. but no snippet.
- No leading spaces (or "empty" char) / lines allowed
- Any number of trailing spaces (or "empty" char) / lines allowed
- Any kind of 1D input is accepted: number, string, array of booleans, etc. Keep the order of bits untouched though.
- Any kind of visual 2D output is accepted: on stdout, a string (with any two distinct values representing "filled" and "empty"), you can even output a matrix if you want. A list of numbers seems hard to reconcile with the "no heading spaces" rule, but I'm open to it if you find a way to use it. Note: if you chose to print or return a string, the characters used must be ASCII characters in the codepoints range [32-126].
- Standard loopholes are banned.
- This is codegolf so the shortest code wins.
Examples
Input: 1
*
Input: 2
**
Input: 3
*
*
Input: 4
***
Input: 5
**
*
Input: 6
*
**
Input: 7
*
*
*
Input: 25
*
***
*
Input: 699050
**
**
**
**
**
**
**
**
**
**
Input: 1047552
*
*
*
*
*
*
*
*
*
***********
Input: 525311
**********
*
*
*
*
*
*
*
*
*
*
29 Answers 29
MATL, 14 bytes
J_iB^YsJ+'o-'&XG
Produces graphical output as a path starting at coordinates (0,0). Try it at MATL Online! Or see some offline examples below:
- Input
7:
Output:
- Input
699050:
Output:
If you prefer, you can see the path as complex coordinates for 9 bytes:
J_iB^YsJ+
###Explanation
J_ % Push -1j (minus imaginary unit)
i % Push input number
B % Convert to binary. Gives an array of 0 and 1 digits
^ % Power, element-wise. A 0 digit gives 1, a 1 digit gives -1j
Ys % Cumulative sum. Produces the path in the complex plane
J+ % Add 1j, element-wise. This makes the complex path start at 0
'o-' % Push this string, which defines plot makers
&XG % Plot
Jelly, 8 bytes
¬œṗ+\Ṭz0
A monadic link accepting a number as a list of ones and zeros (e.g. 13 is [1,1,0,1]) returning a list of lists of ones and zeros where the first list is the first row.
Try it online! or see a formatted test-suite
How?
¬œṗ+\Ṭz0 - Link: list L e.g. [1,1,0,0,1,1,0,1] (i.e. 205)
¬ - logical NOT L [0,0,1,1,0,0,1,0]
\ - cumulative reduce L by:
+ - addition [1,2,2,2,3,4,4,5]
œṗ - partition @ truthy indices [[1,2],[2],[2,3,4],[4,5]]
Ṭ - un-truth (vectorises) [[1,1],[0,1],[0,1,1,1],[0,0,0,1,1]]
z0 - transpose with filler 0 [[1,0,0,0],[1,1,1,0],[0,0,1,0],[0,0,1,1],[0,0,0,1]]
- i.e. 1000
1110
0010
0011
0001
MATL, 10 bytes
YsG~YsQ1Z?
Inputs an array of binary digits. Outputs a matrix.
Explanation
Ys % Implicit input: array of binary digits. Cumulative sum. This gives the
% row coordinates
G % Push input again
~ % Negate: change 0 to 1 and 1 to 0
Ys % Cumulative sum
Q % Add 1. This gives the column coordinates
1Z? % Matrix containing 1 at those row and column coordinates and 0 otherwise.
% Implicit display
05AB1E, (削除) 18 (削除ここまで) (削除) 17 (削除ここまで) 14 bytes
γ€gć ̧s>«1IÔ·ÌΛ
Explanation
γ€g # Push the input as the array as chuncks of consecutive elements, map with length
ć ̧s>« # Increment each value except the first one
1I # Push 1 and the input
Ô # Push connected uniquified input (first elements of each chunck of consecutive elements in the input)
·Ì # Map each with 2 * a + 2
Λ # Draw canvas :-)
- 3 bytes thanks to @Emigna
-
1\$\begingroup\$
γ€gć¸s>«1IÔ·ÌΛshould save 4 bytes. \$\endgroup\$Emigna– Emigna2018年04月06日 10:19:52 +00:00Commented Apr 6, 2018 at 10:19 -
\$\begingroup\$ @Emigna Brilliant, thanks ! Totally forgot that there was an a+2 builtin o: \$\endgroup\$user2956892– user29568922018年04月06日 10:22:56 +00:00Commented Apr 6, 2018 at 10:22
-
\$\begingroup\$ I realize these weren't possible yet when you posted your answer, but you can save 3 bytes now in the new 05AB1E version by changing
γ€gtoÅγ;ć¸s>«to>ć<šand1Ito$: Try it online:Åγ>ć<š$Ô·ÌΛ. \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2020年04月01日 12:27:47 +00:00Commented Apr 1, 2020 at 12:27
Python 2, (削除) 100 (削除ここまで) (削除) 99 (削除ここまで) (削除) 81 (削除ここまで) (削除) 78 (削除ここまで) (削除) 73 (削除ここまで) 66 bytes
a='';x=0
for c in input():a+=('\n'+' '*x)*c+'*';x+=1-c
print a[1:]
Recursive version:
Python 2, (削除) 71 (削除ここまで) (削除) 69 (削除ここまで) 67 bytes
f=lambda n,x=0:n and('\n'[:x]+' '*x)*n[0]+'*'+f(n[1:],x+1-n[0])or''
Charcoal, (削除) 22 (削除ここまで) (削除) 20 (削除ここまで) (削除) 19 (削除ここまで) (削除) 11 (削除ここまで) 10 bytes
F⮌S¿Iι↑*←*
Only my second Charcoal answer thus far.
Takes the input as binary-String (i.e. 699050 as 10101010101010101010).
-9 bytes thanks to @Neil suggesting to loop backwards.
Explanation:
Read STDIN as string in reversed order:
Reverse(InputString())
⮌S
Loop over its binary digits as strings ι:
For(Reverse(InputString()))
F⮌S
If ι casted back to a number is 1, print the * upwards, else print the * towards the left.
If(Cast(i)) Print(:Up,"*"); Else Print(:Left,"*");
¿Iι↑*←*
-
1\$\begingroup\$ This would be half as long if you printed the string in reverse, starting at the end and working up and left. \$\endgroup\$Neil– Neil2018年04月06日 12:39:13 +00:00Commented Apr 6, 2018 at 12:39
-
\$\begingroup\$ @Neil Ok, now it should be fixed. Thanks! -8 bytes \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2018年04月06日 12:56:29 +00:00Commented Apr 6, 2018 at 12:56
-
1\$\begingroup\$ Save another byte by removing the
{}s. \$\endgroup\$Neil– Neil2018年04月06日 13:00:22 +00:00Commented Apr 6, 2018 at 13:00 -
1\$\begingroup\$
Baseonly costs 1 byte as you don't need theCastat all:F⮌↨N²¿ι↑*←*. \$\endgroup\$Neil– Neil2018年04月06日 15:30:55 +00:00Commented Apr 6, 2018 at 15:30 -
1\$\begingroup\$ @KevinCruijssen Sorry for the late reply, but to answer your questions: there is no reverse of
-v, since Charcoal was designed as a golfing language, and I added verbose mode just to make it easier to type and understand. (I can add one if you want though).-ais short for--ast, I added it (format taken from PyTek btw) to help me understand the succinct code with as little effort as possible :P (and it really helps when you've accidentally messed up argument order). Also, not that-lis a separate option. (also just do-hfor help on/descriptions of command-line args) \$\endgroup\$ASCII-only– ASCII-only2018年05月02日 08:41:06 +00:00Commented May 2, 2018 at 8:41
C# (.NET Core), (削除) 155 (削除ここまで) (削除) 123 (削除ここまで) (削除) 120 (削除ここまで) (削除) 113 (削除ここまで) 101 bytes
Saved 32 bytes due to input being able to be received as an array of bits.
Saved 7 bytes thanks to @auhmaan.
Saved 10 bytes thanks to @KevinCruijssen.
n=>{var m="";for(int i=0,c=1;i<n.Length;)m+=n[i++]<1?c++%1+"":(i>1?"\n":"")+"0".PadLeft(c);return m;}
-
\$\begingroup\$ Can't you change the
+new string(' ',c)+"*"to+"*".PadLeft(c)( saves 7 bytes ) ? \$\endgroup\$auhmaan– auhmaan2018年04月06日 11:51:48 +00:00Commented Apr 6, 2018 at 11:51 -
\$\begingroup\$ @auhmaan You're right, thanks! \$\endgroup\$Ian H.– Ian H.2018年04月06日 11:55:13 +00:00Commented Apr 6, 2018 at 11:55
-
\$\begingroup\$ -4 bytes by printing
0instead of*:if(n[i++]<1){m+="*";c++;}toif(n[i++]<1)m+=c++%1;and"*".PadLeft(c);to"0".PadLeft(c);\$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2018年04月06日 13:12:10 +00:00Commented Apr 6, 2018 at 13:12 -
\$\begingroup\$ Correction, it's actually -12 bytes because
m+=can now be a ternary-if:m+=n[i++]<1?c++%1+"":(i>1?"\n":"")+"0".PadLeft(c);\$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2018年04月06日 13:13:42 +00:00Commented Apr 6, 2018 at 13:13 -
1\$\begingroup\$ @KevinCruijssen Thanks, using
0's and the use of the ternary operator is really smart! I also fixed the case for699060, by simply settingcto one the beginning, I kinda missed that while checking the test cases. \$\endgroup\$Ian H.– Ian H.2018年04月06日 17:17:18 +00:00Commented Apr 6, 2018 at 17:17
Haskell, 65 bytes
f(a:b)|a="*":f b|(x:y)<-f b=('*':x):map(' ':)y
f[]=["*"]
f.tail
Takes input as a list of booleans.
Curry PAKCS, 70 bytes
u(a:b)=('*':a):map(' ':)b
f(a:b)|a="*":f b|1>0=u$f b
f[]=["*"]
f .tail
Port of the Haskell answer, but because <- doesn't work in Curry we need to make a helper function u. We also need to add a space between f and . so that Curry parses it as a compose rather than a dot.
This also works in MCC Curry, but doesn't work in Sloth Curry (which is the only one supported by TIO).
Python 2, 59 bytes
s=p='\n'
for x in input():s+=p*x+'*';p+=' '[x:]
print s[2:]
Based off TFeld's solution.
Haskell, (削除) 74 (削除ここまで) (削除) 70 (削除ここまで) (削除) 67 (削除ここまで) 62 bytes
tail.("\n"%)
s%(x:r)=([1..x]>>s)++'*':(s++[' '|x<1])%r
s%[]=""
Try it online! Takes a list of zeros and ones as input and returns a newline separated string.
Inspired by xnor's answer.
-
1\$\begingroup\$ A little friendly competition. \$\endgroup\$2018年04月09日 01:50:31 +00:00Commented Apr 9, 2018 at 1:50
-
1\$\begingroup\$ @user56656 Your turn again :) \$\endgroup\$Laikoni– Laikoni2018年04月09日 07:32:31 +00:00Commented Apr 9, 2018 at 7:32
Emojicode, 251 bytes
🐖🎅🏿🍇🍦b🔡🐕2🍦c🔤*🔤🍮e🔤🔤🍮y🔤🔤🍦k🍡b🔂i k🍇🍊😛🔡i🔤1🔤🍇🍊😛y e🍇🍉🍓🍇😀y🍉🍮y🔤🔤🍮y🍪e c🍪🍉🍓🍇🍮y🍪y c🍪🍮e🍪🔤 🔤 e🍪🍉🍉😀y🍉
This is definitly not a golfed solution, but there isn't a person alive that would consider Emoji-code a golfing language. However, in the process of subjecting myself to the horrors that are emoji-code's syntax in an effore to teach myself this monstrosity of a language, I've been pleasantly surprised by just how powerful and efficient it can be 😀
Explaination:
🐋 🚂 🍇 👴 Define Class
🐖🎅🏿🍇 👴 Define Method
🍦b🔡🐕2 👴Convert Input integer to binary string
🍦c🔤*🔤 👴 asterisk string
🍮e🔤🔤 👴 Spacing string
🍮y🔤🔤 👴 output string
🍦k🍡b 👴 translate to iteratable
🔂i k🍇 👴 for-in loop to iterate over each digit
🍊😛🔡i🔤1🔤🍇 👴 if digit is 1:
🍊😛y e🍇🍉 👴 don't print initial newline
🍓🍇😀y🍉 👴 print spaces + asterisks
🍮y🔤🔤 👴 reset output string
🍮y🍪e c🍪🍉 👴 add correct number of spaces and one asterisk
🍓🍇 👴 if digit is 0:
🍮y🍪y c🍪 👴 add an asterisk to the output string
🍮e🍪🔤 🔤 e🍪 👴 add another space to the space string
🍉🍉
😀y 👴 print one last output string
🍉🍉
🏁🍇 👴 Start Program
🎅🏿 699050 👴 Call Method
🍉
JavaScript (ES6), 48 bytes
Same I/O format and same logic as the recursive version below.
a=>a.map((n,i)=>n?i&&p+0:+(p+=' '),p=`
`).join``
Or 42 bytes if this format is acceptable.
Recursive version, 56 bytes
Takes input as an array of integers (0 or 1). Uses 0 for filled and space for empty.
f=([n,...a],p=`
`,x=0)=>1/n?(n?x+0:+(p+=' '))+f(a,p,p):a
Commented
f = ( // f = recursive function taking:
[n, ...a], // n = current bit; a[] = remaining bits
p = `\n`, // p = padding string, initialized to a linefeed
x = 0 // x = 0 on the 1st iteration / equal to p after that
) => //
1 / n ? // if n is defined:
( n ? // if n = 1:
x + 0 // append x + 0 --> either the integer 0 on the first iteration
// or the padding string followed by a '0'
: // else:
+( // append the integer 0 (whitespace coerced to a number)
p += ' ' // and append a space to the padding string
) //
) + f(a, p, p) // append the result of a recursive call with x = p
: // else:
a // append the empty array a[], forcing coercion to a string
Bash + GNU utilities, 38
dc -e?2op|sed 's/\B1/^K^H*/g;s/[10]/*/g'
Here ^K and ^H are literal vertical-tab and backspace control characters. These don't render well on browsers, so this script may be recreated as follows:
base64 -d <<< ZGMgLWU/Mm9wfHNlZCAncy9cQjEvCwgqL2c7cy9bMTBdLyovZyc= > binpath.sh
Run in a terminal. Input is via STDIN.
This answer may stretch the specifications too far - there are in fact no leading characters on each line of output - all positioning is done with control characters. If this is too much of a stretch, then the output may be piped to |col -x|tac for an extra 11 bytes.
Batch, 113 bytes
@set s=
:l
@shift
@if %1.==0. set s=%s%+&goto l
@echo %s%+
@if not %s%.==. set s=%s:+= %
@if %1.==1. goto l
Takes a list of bits as command-line arguments. Uses + instead of * because * has a special meaning inside %s:...=...% expansions.
Java 10, (削除) 100 (削除ここまで) 106 bytes
b->{var s="";int i=0,j;for(var c:b){if(c)for(s+="\n",j=i;j-->0;)s+=0;else++i;s+=1;}return s.substring(1);}
Takes an array of booleans and returns a String (0s are empty, 1s are filled). Try it online here.
Thanks to Olivier Grégoire for helping me golf it a bit more and alerting me to the fact that my output format was not up to the spec.
Ungolfed version:
b -> { // lambda taking an array of booleans as argument
var s = ""; // the output String
int i = 0, // the number of "empty" characters to output
j; // iterator variable for outputting the "empty" characters
for(var c : b) { // iterate over the boolean array (the binary digits)
if(c) // if it's a '1'
for(s += "\n", // output a newline
j = i; j-- > 0;) s += 0; // output the "empty" characters
else // if it's a '0'
++i; // move one to the right on the next line
s += 1; // output the "filled" character
}
return s.substring(1); // output the constructed String, minus the leading newline
}
-
\$\begingroup\$ I golfed 5 bytes:
{if(c){s+="\n";for(j=i;j-->0;)s+=0;}else++i;s+=1;}\$\endgroup\$Olivier Grégoire– Olivier Grégoire2018年04月06日 12:12:53 +00:00Commented Apr 6, 2018 at 12:12 -
\$\begingroup\$ Even further:
{if(c)for(s+="\n",j=i;j-->0;)s+=0;else++i;s+=1;}\$\endgroup\$Olivier Grégoire– Olivier Grégoire2018年04月06日 12:16:03 +00:00Commented Apr 6, 2018 at 12:16 -
\$\begingroup\$ Though, you don't print on the first line but on the second one. From the challenge: "No leading spaces (or "empty" char) / lines allowed" \$\endgroup\$Olivier Grégoire– Olivier Grégoire2018年04月06日 12:19:14 +00:00Commented Apr 6, 2018 at 12:19
-
\$\begingroup\$ @OlivierGrégoire Thanks. I have edited. \$\endgroup\$O.O.Balance– O.O.Balance2018年04月06日 14:33:41 +00:00Commented Apr 6, 2018 at 14:33
Java (JDK 10), 83 bytes
a->{int m[][]=new int[20][20],r=0,i=0;for(int b:a)m[r+=i<1?0:b][i++-r]=1;return m;}
- Supports at most 20 bits.
- Input as
int[] - Output as
int[][]
Haskell, 126 bytes
(#)n=maximum.map(!!n)
f l|s<-scanl1(zipWith(+))$(\a->[1-a,a])<$>l=unlines[[last$' ':['#'|elem[x,y]s]|x<-[0..0#s]]|y<-[1..1#s]]
Input as a list of zeroes and ones. Transforms number into offset by x↦[1-x,x] and calculates the partial sums. Final output is done with two nested list comprehensions.
R, 59 bytes
function(n,x=sum(n|1))matrix(1:x^2%in%cumsum((n-1)%%x+1),x)
Takes input as an array of bits.
Returns a boolean matrix of TRUE and FALSE representing a * and a , respectively.
Also has some stuff in the footer to print a matrix corresponding to the specs above, for ease of testing.
APL+WIN, 65 or 46 bytes
Prompts for input of the integer
n←+/i←((1+⌊2⍟n)⍴2)⊤n←⎕⋄m←(n,n)⍴' '⋄m[⊂[2](+\i),[1.1]1++\~i]←'*'⋄m
or for numerical vector of the binary representation of the integer
m←(2⍴+/n←⎕)⍴' '⋄m[⊂[2](+\i),[1.1]1++\~i]←'*'⋄m
assuming I have read the comments to certain answers correctly and the latter input is allowed.
Pyth, 23 bytes
p\*VtQINp+b*Zd.?=hZ)p\*
Explanation
p\*VtQINp+b*Zd.?=hZ)p\*
p\* Print the leading *.
VtQ For each bit (excluding the leading 1)...
IN .? ) ... If the bit is set...
p+b*Zd ... Print a newline and a bunch of spaces...
=hZ ... Otherwise, increase the count of spaces...
p\* ... Then print the next *.
SmileBASIC, (削除) 64 (削除ここまで) (削除) 59 (削除ここまで) 57 bytes
INPUT N@L
GPSET X,Y
B=N<0X=X+B
Y=Y+(X>B)N=N<<1ON!N GOTO@L
The highest bit (sign bit) is checked, and if it's 1, the X position increases. If the sign bit is less than the X position (that is, the sign bit is 0 and X is not 0) the Y position increases.
The first movement will always be horizontally, so Y movement is blocked until after the first X movement. This ensures that the Y position doesn't increase during the leading 0 bits.
Then N is shifted left, and this repeats until N reaches 0.
Japt, (削除) 19 (削除ここまで) 17 bytes
Ë?R+Tî +Q:°T©Qìx
Ë? // Map over the input and if the current value is 1:
R+ // Return a new line and
Tî + // a space repeated T (with initial value 0) times and
Q // a \".
: // If the current value is 0:
°T // Increment T
©Q // and return \".
à // When all of that is done,
¬ // turn the array into a string
x // and trim it, removing the excess new line at the start.
Takes input as an array of bits, for example [1,0,1], outputs " instead of *.
Shaved two bytes off thanks to Oliver.
-
\$\begingroup\$ Nice one. You can replace
SpTwithTî-îis similar top, except it defaults to" ". Also, there's a shortcut forq:¬\$\endgroup\$Oliver– Oliver2018年04月06日 19:55:07 +00:00Commented Apr 6, 2018 at 19:55 -
\$\begingroup\$ @Oliver Thanks, I didn't know about
î, certainly very handy. I often check for chances to use the shortcuts, but I still always miss some of them, thanks a lot for your help. \$\endgroup\$Etheryte– Etheryte2018年04月07日 07:58:33 +00:00Commented Apr 7, 2018 at 7:58
Python 2, 113 Bytes
def f(a):
o='*';r=[o]
for i in bin(a)[3:]:
if'0'<i:r+=[' '*len(r[-1][1:])]
r[-1]+=o
print'\n'.join(r)
Not sure if this one counts (it outputs an array of each of the lines), but if so then I'll change my byte count to 103:
def f(a):
o='*';r=[o]
for i in bin(a)[3:]:
if'0'<i:r+=[' '*len(r[-1][1:])]
r[-1]+=o
print r
TI-Basic (TI-84 Plus CE), 85 bytes
Prompt L
1→X
1→Y
DelVar [A]
sum(LL
{Ans,1-Ans+dim(LL→dim([A]
1→[A](Y,X
For(I,2,dim(LL
Y+LL(I→Y
X+not(LL(I→X
1→[A](Y,X
End
[A]
Prompts for a boolean list, returns a matrix of 0 and 1.
Goes through the list, incrementing X if the next 'bit' is 0, changing Y otherwise, then adding a 1 to the matrix at that location, and returns the matrix at the end.
TI-Basic is a tokenized lanugage.
- 1 byte:
Prompt,L*6, (newline)*12,1*5,→*7,X*5,Y*5,sum(,L*5,{,Ans*2,,*5,-,+*3,dim(*3,(*4,For(,I*3,2,not(,End= 73 bytes - 2 bytes:
Delvar,[A]*5 = 12 bytes - Total: 85 bytes
TI-Basic (TI-84 Plus CE), 56 bytes
Prompt L
1→X
1→Y
Output(Y,X,"*
For(I,2,dim(LL
Y+LL(I→Y
X+not(LL(I→X
Output(Y,X,"*
End
Same processs as above, but using graphical output (limited by screen size: 10 rows, 26 columns, so max 10 1s and 25 0s) as it goes, instead of adding to a matrix.
Pyth, 30 bytes
JZFG.BQIsGIJk)p+*ZdN.?pN=hZ)=J
Uses " instead of *.
Q=eval(input())
Z=0
J=Z
for G in "{0:b}".format(Q):
if int(G):
if J:
print()
print(Z*' '+'"',end='')
else:
print('"',end='')
Z+=1
J=Q
x86 .COM, 32 bytes
00h: 66 D1 E6 66 0F BD CE BF 24 AD 8E DF 41 66 0F A3
10h: CE 19 DB 81 E3 9E 00 8D 79 02 C6 05 2A E2 EE C3
fun:
shl esi, 1
bsr ecx, esi
mov di, $ad24
mov ds, di
inc cx
lab2:
bt esi, ecx
sbb bx,bx
and bx,158
lea di,[di+2+bx]
mov [di],byte '*'
lab1:loop lab2
ret
[1,0,1], yes. \$\endgroup\$9is1001I'd like my input to be0011. Is that OK? \$\endgroup\$1first is part of the challenge, and (re-)moving that bit would be trivializing the challenge so I'm afraid I'll have to say you no, @TonHospel . You can remove it from your input in the program, though. \$\endgroup\$