26
\$\begingroup\$

Given an integer n ≥ 1, output a 2D representation of a percent sign of width n. The construction goes as follows:

  1. Create an n by n matrix (or list of lists) filled with zeroes.
  2. Insert ones in the top-left and bottom-right corners.
  3. Place ones on the diagonal from the bottom-left to the top-right.

For input n = 4, this construction would look like:

1. 4x4 matrix of 0s
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
2. 1s in TL and BR corners
1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 1
3. 1s across BL-TR diagonal
1 0 0 1
0 0 1 0
0 1 0 0
1 0 0 1

This is a , so the shortest program in bytes wins.

I use a matrix of 1s and 0s, but it is also acceptable to use a string of any non-whitespace character and spaces. So, the example above could look like:

#  #
  # 
 #  
#  #

or

#     #
    #
  # 
#     #

Test cases

n
output

1
1

2
1 1
1 1

3
1 0 1
0 1 0
1 0 1

4
1 0 0 1
0 0 1 0
0 1 0 0
1 0 0 1

10
1 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 1

Final note

Adding an explanation would be greatly appreciated.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Can our solutions be 0-indexed? \$\endgroup\$
    – user41805
    Commented Jul 21, 2017 at 17:41
  • 6
    \$\begingroup\$ @Cowsquack I'd say no. You're receiving the width, not an index. \$\endgroup\$ Commented Jul 21, 2017 at 17:44
  • \$\begingroup\$ Can we output a list of lists? \$\endgroup\$
    – xnor
    Commented Jul 21, 2017 at 18:02
  • \$\begingroup\$ @xnor Yes; list of lists and matrix are synonymous in my post. I'll add that to the question \$\endgroup\$ Commented Jul 21, 2017 at 18:15
  • \$\begingroup\$ Note that this is '1'+'0'*(n-2) with whitespace inserted \$\endgroup\$ Commented Jul 21, 2017 at 21:30

50 Answers 50

11
\$\begingroup\$

JavaScript (ES6), 52 bytes

n=>[...Array(n)].map((_,y,a)=>a.map(_=>y++%~-n<1|0))
\$\endgroup\$
0
10
\$\begingroup\$

Jelly, 6 bytes

²Rm’Ṭs

Try it online!

How it works

²Rm’Ṭs  Main link. Argument: n

²       Square; yield n².
 R      Range; yield [1, ..., n²].
   ’    Decrement; yield n-1.
  m     Modular; yield every (n-1)-th element of the range, staring with the first.
    Ṭ   Untruth; yield a Boolean array with 1's at the specified indices.
     s  Split the resulting array into chunks of length n, creating a matrix.
\$\endgroup\$
5
  • \$\begingroup\$ Also, ²Ḷ%’¬s or +þ%’=2 \$\endgroup\$ Commented Jul 21, 2017 at 17:52
  • \$\begingroup\$ ²Ḷọ’s is so close... \$\endgroup\$
    – Dennis
    Commented Jul 21, 2017 at 17:57
  • \$\begingroup\$ If only there were a 1-byte "x is divisible by y" link... \$\endgroup\$ Commented Jul 21, 2017 at 17:58
  • \$\begingroup\$ @ETHproductions There's ḍ@ but that's two bytes. \$\endgroup\$ Commented Jul 21, 2017 at 19:14
  • \$\begingroup\$ And I thought I was clever with ⁼þµ+1¦Ṫṁ³UG...until a Dennis ²-something solution popped up. \$\endgroup\$ Commented Jul 21, 2017 at 19:15
8
\$\begingroup\$

V, 15 bytes

Àé ÀÄ|r#L.|ò.kl

Try it online!

Explanation

Àé<space>        " Argument times insert a space
ÀÄ               " Argument times duplicate this line
                 " This gives an arg-by-arg matrix of spaces
                 "  and brings the cursor to the end of the first line
|r#              " Go to the beginning of this line and replace the first character with #
L.               " Go to the end of this matrix (bottom-right corner) and replace that character with a #
|                " Go to the beginning of the last line
ò                " Recursively do:
 .               "  Repeat the last action, r#, replace the character under the cursor with #
 kl              "  Go 1 up and 1 right
\$\endgroup\$
7
\$\begingroup\$

Python 2, 58 57 bytes

n=input()
x='#'.ljust(n-1)*3
exec'print x[:n];x=x[1:];'*n

Try it online!

\$\endgroup\$
7
\$\begingroup\$

Dyalog APL, 12 11 10 bytes

,⍨⍴×,2↓⊢↑×

Try it online

-1 byte thanks to lstefano.

How?

,⍨⍴×,2↓⊢↑×
       ⊢↑× - argument-length extension of the sign of the argument (1)
     2↓    - Drop the first two elements
   ×,      - Prepend a one
,⍨⍴        - Shape into a square array with dimensions of input x input
\$\endgroup\$
4
  • \$\begingroup\$ I seriously don't think this can be golfed anymore... wow. \$\endgroup\$
    – Adalynn
    Commented Jul 23, 2017 at 15:35
  • \$\begingroup\$ It can: ,⍨⍴×,2↓⊢↑× (10 bytes). I am tempted to add: don't use too many commutes... :-P \$\endgroup\$
    – lstefano
    Commented Aug 2, 2017 at 8:49
  • \$\begingroup\$ Try online with arg 5 - Try online with arg 1 \$\endgroup\$
    – lstefano
    Commented Aug 2, 2017 at 8:53
  • \$\begingroup\$ You've got to be kidding me, wow. Nice abuse of signum. \$\endgroup\$
    – Adalynn
    Commented Aug 14, 2017 at 18:09
6
\$\begingroup\$

GNU APL, 17 15 bytes

{1=⍵∨⍵⍵⍴1=⍳⍵-1}

This is one weird day ... GNU actually beat Dyalog APL ... woah.

TIO doesn't support GNU APL ...

Explanation (input is ):

1=⍳⍵-1 - 1 followed by ⍵-2 0's
⍵⍵⍴    - fit into a square
⍵∨     - gcd ⍵ (0 gcd n = n)
1=     - test each element for equality with 1
\$\endgroup\$
8
  • \$\begingroup\$ Ninja'd? \$\endgroup\$
    – user41805
    Commented Jul 21, 2017 at 18:25
  • \$\begingroup\$ There ... take that. \$\endgroup\$
    – Adalynn
    Commented Jul 21, 2017 at 18:28
  • \$\begingroup\$ Can't believe I actually had to break out my old GNU APL, wow. \$\endgroup\$
    – Adalynn
    Commented Jul 21, 2017 at 18:30
  • \$\begingroup\$ And take that!! \$\endgroup\$
    – Adalynn
    Commented Jul 21, 2017 at 18:36
  • \$\begingroup\$ Ooh, I am going to take inspiration from the 1=⍵∨ and implement it in my solution \$\endgroup\$
    – user41805
    Commented Jul 21, 2017 at 18:44
6
\$\begingroup\$

Python 2, 46 bytes

lambda n:zip(*[iter(`10L**n`[:-3]*-~n+'1')]*n)

Try it online!

Outputs like

[('1', '0', '0', '1'), ('0', '0', '1', '0'), ('0', '1', '0', '0'), ('1', '0', '0', '1')]

Python 2, 48 bytes

lambda n:zip(*[iter([1]+(n*[0]+[1])[2:]*-~n)]*n)

Try it online!

Outputs like

[(1, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, 0), (1, 0, 0, 1)]

Python 3, 48 bytes

lambda n:('%d'*n+'\n')*n%(1,*(*[0]*n,1)[2:]*-~n)

Try it online!

A quite different string-substitution approach in Python 3. Outputs like:

1001
0010
0100
1001
\$\endgroup\$
3
  • \$\begingroup\$ Can't you make 10L 10? \$\endgroup\$
    – Adalynn
    Commented Jul 30, 2017 at 20:08
  • \$\begingroup\$ @Zacharý I'm relying on there always being an L at the end so I can cut the same number of characters off the end of large numbers and small ones. \$\endgroup\$
    – xnor
    Commented Jul 30, 2017 at 20:20
  • \$\begingroup\$ Oh, sorry, I mistakenly thought you were only using it as the number. I never knew 10 and 10L were different. \$\endgroup\$
    – Adalynn
    Commented Jul 30, 2017 at 20:22
6
\$\begingroup\$

MATL, 7 bytes

XyPl5L(

Try it at MATL Online!

Explanation

Create identity matrix (Xy), flip vertically (P), write (() value 1 (l) to the first and last entries (5L), which are the top left and bottom right.

\$\endgroup\$
5
\$\begingroup\$

Jelly, 9 bytes

=þ¹UF1Q¦s

Try it online!

How it works

=þ¹UF1Q¦s  Main link. Argument: n

  ¹        Identity; yield n.
=þ         Equals table; compare each i in [1, ..., n] with each j in [1, ..., n].
           This yields the n×n identity matrix.
   U       Upend; reverse each row.
    F      Flatten the matrix.
       ¦   Sparse application:
      Q        Unique; yield the unique elements of the constructed array, i.e.,
               [1] if n = 1 and [0, 1] if n > 1.
     1         Yield 1.
           This replaces the elements at indices 0 (last) and 1 (first) with 1.
        s  Split the resulting array into chunks of length n.
\$\endgroup\$
5
\$\begingroup\$

APL (Dyalog), 18 bytes

{⍵=1:⍵⋄⍵ ⍵⍴1=⍳⍵-1}

Try it online!

Making this work for input 1 has added 6 bytes.

Looking at testcase 4, we see the output is

1 0 0 1
0 0 1 0
0 1 0 0
1 0 0 1

This is basically 1 0 0 repeated throughout the matrix. In other words, 1 0 0 shaped in a 4-by-4 matrix. So in this solution, we first generate this vector with 1 and trailing 0s using 1=⍳⍵-1 and then shape it using ⍵ ⍵⍴. But this borks for input 1, so we need to create a conditional and gain 6 bytes...

{⍵=1:⍵⋄⍵ ⍵⍴1=⍳⍵-1}    The right argument is ⍵
 ⍵=1:⍵                 If ⍵ is 1 return itself
⋄                      Otherwise
 ⍳⍵-1                   Create a range 1 .. ⍵-1
 1=                     Equals 1; 1 0 0 {⍵-2 0's} ...
 ⍵ ⍵⍴                   Shape in a ⍵-by-⍵ matrix
\$\endgroup\$
1
  • \$\begingroup\$ Could you replace the conditional with 1⌈⍵-1? i.e. {⍵ ⍵⍴1=⍳1⌈⍵-1} \$\endgroup\$
    – coltim
    Commented Nov 2, 2020 at 0:23
4
\$\begingroup\$

05AB1E, 14 11 7 bytes

n<ÝI<Öô

Try it online!

Explanation

n<Ý      # push range [0 ... n^2-1]
   I<Ö   # check each for equality to 0 when modulus with n-1 is taken
      ô  # split in pieces of size n
\$\endgroup\$
4
\$\begingroup\$

Haskell, 55 bytes

At first my approach was to recursively generate the transposed identity matrix, but then fixing the first and last line required some ugly/lengthy case distinctions. So I looked for another way to generate the identity matrix which is how I found this idea.

f n=[[sum[1|x+y`elem`[2,n+1,2*n]]|y<-[1..n]]|x<-[1..n]]

Try it online!

Explanation

[[x+y|y<-[1..n]]|x<-[1..n]]

generates this matrix (for n=4):

[2,3,4,5]
[3,4,5,6]
[4,5,6,7]
[5,6,7,8]

As you can see the top left element is 2 (in general), all the diagonal elements are 5 (in general n+1) and the bottom right element is 8 (in general 2*n). So all we need to do is to check if x+y is an element of [2,n+1,2*n].

\$\endgroup\$
4
\$\begingroup\$

R, 54 42 bytes

-12 bytes thanks to Jarko Dubbeldam

n=scan();m=diag(n)[,n:1];m[1,1]=m[n,n]=1;m

returns a matrix; reads from stdin. creates an identity matrix diag(n), flips it top to bottom [,n:1], sets the top left and bottom right to 1, and then writes to console ('') with width n.

Try it online!

\$\endgroup\$
10
  • \$\begingroup\$ You are allowed to output a matrix, so you can save a few bytes by turning it into a function (pryr::f). \$\endgroup\$
    – JAD
    Commented Jul 21, 2017 at 19:03
  • \$\begingroup\$ @JarkoDubbeldam I could, but then I think I'd have to change the language to R+pryr so I'd consider that a separate language; you're free to submit that! Then you could use the idea from Cows quack's answer which I think would be even shorter than this in that context (a 1-liner). \$\endgroup\$
    – Giuseppe
    Commented Jul 21, 2017 at 20:04
  • \$\begingroup\$ Hmm, I am unsure where to draw the line to be honest. Would you consider any library used a different language? \$\endgroup\$
    – JAD
    Commented Jul 21, 2017 at 20:25
  • 1
    \$\begingroup\$ Also, using function(n) would probably still be shorter \$\endgroup\$
    – JAD
    Commented Jul 21, 2017 at 20:30
  • 1
    \$\begingroup\$ Which is shorter than the oneliner implementation you referenced: function(n)matrix(rep(c(1,rep(0,n-2)),n+1),n,n) \$\endgroup\$
    – JAD
    Commented Jul 21, 2017 at 20:35
4
\$\begingroup\$

Easyfuck, 21 19 bytes

EM:␗Èc°NSHYå·Ñß'xSHYâÛNBSP

due to lack of unicode representations for c1 control characters, they have been replaced by their superscripted abbreviations

Decompressed:

"S'!>!G0'+<[>G>'<+<-]

"S' take input, put it into storage and output 0

!>!G0' move cursor to [input, input] and output 0

+<[>G>'<+<-] move cursor to [input, 1] and output 0s while moving to [1, input]

\$\endgroup\$
3
\$\begingroup\$

PowerShell, 67 bytes

param($n)0..--$n|%{-join(("1"+"0"*(($n-1),0)[!$n])*3)[$_..($_+$n)]}

Try it online!

Takes input $n and loops from 0 to --$n (i.e., $n pre-decremented). Each iteration, we construct a string of 1 followed by $n-1 0s, then multiply that out 3 times (e.g., 100010001000 for input of 5). Then we index into that on a rotating basis starting from 0 to 0 + $n. Those characters are -joined into a string, which is left on the pipeline. Output is implicit.


(NB -- This requires an additional 9 bytes to handle the special case of n=1. Below is the 58-byte code if we're guaranteed n>1)

param($n)0..--$n|%{-join(("1"+"0"*($n-1))*3)[$_..($_+$n)]}
\$\endgroup\$
3
\$\begingroup\$

C# (.NET Core),121 91 88 bytes

-30 bytes because the old way was stupid.

-3 bytes by moving around the variable initialization

n=>{int i=0,k=n-1;int[,]b=new int[n,n];b[0,0]=b[k,k]=1;for(;i<n;)b[i++,k--]=1;return b;}

Try it online!

Loops iterates down the array to fill in the 1's. Returns an array of 1's and 0's.

\$\endgroup\$
1
  • \$\begingroup\$ Declare b as var to save some bytes. \$\endgroup\$ Commented Jul 24, 2017 at 8:02
3
\$\begingroup\$

Charcoal, 14 12 7 bytes

-5 bytes thanks to Neil!

↗N⸿/‖O↘

Try it online!

\$\endgroup\$
4
  • \$\begingroup\$ I don't think this can be any shorter... \$\endgroup\$ Commented Jul 21, 2017 at 19:25
  • 1
    \$\begingroup\$ Well, first I trimmed it to Nν◨/ν←↙ν‖O↘, but then I came up with ↗N⸿/‖O↘! \$\endgroup\$
    – Neil
    Commented Jul 21, 2017 at 19:27
  • \$\begingroup\$ @Neil Wow, I don't even know what ⸿ does. Does it reset to original position? \$\endgroup\$
    – notjagan
    Commented Jul 21, 2017 at 19:41
  • \$\begingroup\$ No, ⸿ is like in that it moves down a row but it always goes to column zero (as measured by ) rather than the column at the beginning of the string, so for example J⁵¦⁵⸿ is the same as J⁰¦⁶. \$\endgroup\$
    – Neil
    Commented Jul 21, 2017 at 23:05
3
\$\begingroup\$

C++, 144 bytes

#include<string>
#define S std::string
S p(int n){S r;for(int i=0;i<n;++i){r+=S(n,32);r[r.size()-1-i]=35;r+=10;}r[0]=r[r.size()-2]=35;return r;}

It takes advantage of the one byte difference between '#' and 35

\$\endgroup\$
2
  • \$\begingroup\$ Where exactly does your code take advantage of the one byte difference between '#' and 35? \$\endgroup\$
    – Adalynn
    Commented Jul 30, 2017 at 22:41
  • \$\begingroup\$ @Zacharý It seems it was in my IDE x) \$\endgroup\$ Commented Jul 30, 2017 at 22:58
2
\$\begingroup\$

Mathematica, 72 bytes

(s=Table[0,#,#];s[[1,1]]=s[[#,#]]=1;Table[s[[#+1-i,i]]=1,{i,#}];Grid@s)&

input

[5]

output

1 0 0 0 1
0 0 0 1 0
0 0 1 0 0
0 1 0 0 0
1 0 0 0 1

\$\endgroup\$
1
  • 1
    \$\begingroup\$ The problem doesn't ask you to print/display it, so you can replace Grid@s with s to save 5 bytes. \$\endgroup\$
    – Mark S.
    Commented Jul 30, 2017 at 22:56
2
\$\begingroup\$

Python 2, 86 62 bytes

n=input();a=('1'+'0'*(n-2))*2+'1'
exec'print a[:n];a=a[1:];'*n

Try it online!

-24 bytes: Thanks to an idea from Rod!

\$\endgroup\$
2
\$\begingroup\$

Dyalog APL v16, 23 bytes

{(1@(1 1)(⍵ ⍵))⌽∘.=⍨⍳⍵}

Try it online!

Explanation:

{(1@(1 1)(⍵ ⍵))⌽∘.=⍨⍳⍵} -(input ⍵) 
                ∘.=⍨⍳⍵  - identity matrix with size ⍵×⍵
               ⌽        - flip that
 (1@(1 1)(⍵ ⍵))         - place 1 into the corners using the v16 operator @ (At)
\$\endgroup\$
2
\$\begingroup\$

Lua, 117 bytes

m=arg[1]+0 for y=m,1,-1 do s=""for x=1,m do s=s..((x==1 and y==m or x==m and y==1 or x==y)and"#"or" ")end print(s)end

Try it

Code is pretty simple. It sets m to the first argument, then adds 0 to it to convert it to a number, then iterates backwards for the Y coord, forward through the X coord and will put a # if x==y or if it's the other corners.

This program never uses the keyword "if".

\$\endgroup\$
2
\$\begingroup\$

Octave, 37 bytes

@(n)sparse([1 n:-1:1 n],[1 1:n n],!0)

Try it online!

Generates a sparse matrix representing the percent sign.

\$\endgroup\$
2
\$\begingroup\$

Japt, 12 bytes

²ovUÉ hT1 òU

Returns a 2D array / matrix.

Try it online! using the -Q flag to show array-formatted output.

Explanation

²ovUÉ hT1 òU

Implicit: U = input integer

²o

Square U (²), create the array [0, U*U) (o), and map each item by...

vUÉ

1 if it's divisible (v) by U-1 (), else 0.

hT1

Set the item (h) at index 0 (T) to 1.

òU

Split the array into slices (ò) of length U.

\$\endgroup\$
3
  • \$\begingroup\$ I don't think you actually need the hT1, as 0 is technically already divisible by U for every U. Other than that, great job :-) \$\endgroup\$ Commented Jul 21, 2017 at 19:49
  • \$\begingroup\$ @ETHproductions That was added to deal with an input of 1. Without it, it returns [[0]] because apparently zero is not divisible by zero. \$\endgroup\$ Commented Jul 21, 2017 at 19:52
  • \$\begingroup\$ Ah, dang it. I don't know if I should fix that though... \$\endgroup\$ Commented Jul 21, 2017 at 19:57
2
\$\begingroup\$

PHP, 53 bytes

for(;$i<$l*$l;)echo($i++%($l-1)?0:1).($i%$l?'':"\n");

The length of the side of the matrix is $l. This code has a PHP Notice and even a PHP Warning for division by 0 when $l=0, but does the job!

\$\endgroup\$
3
  • \$\begingroup\$ It seems that you expect the input to be stored in a predefined variable (->$l). Unfortunately this is not one of our accepted ways to take input. In the linked meta post you'll find alternatives, e.g. using command line arguments as seen in ricdesi's answer. \$\endgroup\$
    – nimi
    Commented Jul 22, 2017 at 10:03
  • \$\begingroup\$ completed and golfed: while($i**.5<$n=$argn)echo$i++%~-$n?0:1,"\n"[$i%$n]; or while($i**.5<$n=$argn)echo+!($i++%~-$n),"\n"[$i%$n]; (52 bytes each) \$\endgroup\$
    – Titus
    Commented Jul 22, 2017 at 16:05
  • \$\begingroup\$ Needs <? at the beginning. \$\endgroup\$ Commented Jul 23, 2017 at 4:17
2
\$\begingroup\$

Python 2, 93 bytes

n=input()
a='1'+'0'*(n-2)+'1'
print a
for i in range(1,n-1):print str(10**i).zfill(n)
print a

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Good try, but doesnt work for n=1. \$\endgroup\$ Commented Jul 22, 2017 at 6:35
2
\$\begingroup\$

Ruby, 47 bytes

->n{([1]+[0]*(n-2)).cycle.each_slice(n).take n}

It returns an array of arrays.

The code is pretty straightforward.

  • It creates a n-1 array with 1 as the first element and the rest filled with 0s (e.g. [1, 0, 0, 0])
  • It repeats it
  • It takes n slices of n elements

Try it online!

\$\endgroup\$
2
\$\begingroup\$

J, 14 bytes

-]\*:$1,0$~-&2 

Ungolfed:

- ]\ (*: $ (1,0 $~ -&2))

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ Food for thought: a 10 byte solution exists :) \$\endgroup\$ Commented Jul 29, 2017 at 7:13
  • \$\begingroup\$ @ConorO'Brien Damn you. It's already past 3 am here :P \$\endgroup\$
    – Jonah
    Commented Jul 29, 2017 at 7:13
  • \$\begingroup\$ Same here, and here we are :D \$\endgroup\$ Commented Jul 29, 2017 at 7:14
  • 1
    \$\begingroup\$ @ConorO'Brien Was it 0=<:|i.@,~? \$\endgroup\$
    – miles
    Commented Jul 30, 2017 at 4:56
  • \$\begingroup\$ @miles yes, it was :) \$\endgroup\$ Commented Jul 30, 2017 at 4:58
2
\$\begingroup\$

Python 3, 97 bytes

def f(n):
    m=[[0+(j==n-i-1)for j in range(n)]for i in range(n)]
    m[0][0]=1
    m[-1]=m[0]
    return m

Explanation

m=[[0+(j==n-i-1)for j in range(n)]for i in range(n)]

This is a list comprehension, the 0+(j==n-i-1) is a shorter way to convert j==n-i-1 to an int (as opposed to int function) and then m[-1]=m[0] is shorter than making bottom right 1, as top and bottom rows are identical.

\$\endgroup\$
0
2
\$\begingroup\$

Forth, 273 ( without comments ) 170 ( golfed-ish )

: % 2 base ! cr dup 1- 1 swap lshift 1 or . cr 2 over 2 - dup 0< 0= if
0 ?do 2dup s>d rot <# 0 ?do # loop #> type cr 2*  loop
1 or . else drop drop then cr drop decimal ;

( 273 version to clarify commented version: )

: newbase
 base @ swap base ! ;
: 0u.r
 swap s>d rot <# 0 ?do # loop #> type ;
: frame
 1- 1 swap lshift 1 or ;
: %
 2 newbase swap
 cr dup frame . cr
 2 over 2 -
 dup 0< 0= if
  0 ?do
   2dup swap 0u.r cr
   2* 
  loop
  1 or .
 else
  drop drop
 then
cr
drop base ! ;

( Note that, since whitespace is the primary delimiter in Forth, removing every carriage return would make no difference. Indentation, of course, does. )

( Commented: )

( Uses bit array, max 64 width on AMD64 with gforth. )

( Could shave an extra thirty or so bytes by not restoring )
( the numeric base, )
( and a few more by pulling frame and 0u.r into the definition. )

: newbase ( n -- oldbase )  ( swap base with n )
 base @ swap base ! ;

: 0u.r ( u width -- )  ( unsigned numeric output, no leading zero suppression )
 swap s>d rot <# 0 ?do # loop #> type ;

: frame ( n -- f )  ( frame )
 1- 1 swap lshift 1 or ;

: %  ( n -- )  ( Make the % sign )
 2 newbase swap ( Use binary output. )
 cr dup frame . cr ( Frame the first line. )
 2 over 2 -
 dup 0< 0= if ( Are we already done? )
  0 ?do ( Loop doesn't do the first or last. )
   2dup swap 0u.r cr ( Zero fill, right justify. )
   2* 
  loop
  1 or . ( Put the second frame out. )
 else
  drop drop
 then
cr
drop base ! ;

( Execution examples: )

1 % 
1 

 ok
2 % 
11 
11 
 ok
3 % 
101 
010
101 
 ok
10 % 
1000000001 
0000000010
0000000100
0000001000
0000010000
0000100000
0001000000
0010000000
0100000000
1000000001 
 ok
40 % 
1000000000000000000000000000000000000001 
0000000000000000000000000000000000000010
0000000000000000000000000000000000000100
0000000000000000000000000000000000001000
0000000000000000000000000000000000010000
0000000000000000000000000000000000100000
0000000000000000000000000000000001000000
0000000000000000000000000000000010000000
0000000000000000000000000000000100000000
0000000000000000000000000000001000000000
0000000000000000000000000000010000000000
0000000000000000000000000000100000000000
0000000000000000000000000001000000000000
0000000000000000000000000010000000000000
0000000000000000000000000100000000000000
0000000000000000000000001000000000000000
0000000000000000000000010000000000000000
0000000000000000000000100000000000000000
0000000000000000000001000000000000000000
0000000000000000000010000000000000000000
0000000000000000000100000000000000000000
0000000000000000001000000000000000000000
0000000000000000010000000000000000000000
0000000000000000100000000000000000000000
0000000000000001000000000000000000000000
0000000000000010000000000000000000000000
0000000000000100000000000000000000000000
0000000000001000000000000000000000000000
0000000000010000000000000000000000000000
0000000000100000000000000000000000000000
0000000001000000000000000000000000000000
0000000010000000000000000000000000000000
0000000100000000000000000000000000000000
0000001000000000000000000000000000000000
0000010000000000000000000000000000000000
0000100000000000000000000000000000000000
0001000000000000000000000000000000000000
0010000000000000000000000000000000000000
0100000000000000000000000000000000000000
1000000000000000000000000000000000000001 
 ok

( Final note: works to one less than the bit width of the Forth interpreter. I ran the above on gforth, AMD64. An ancient 16-bit Forth would only go to 15 bits wide, and would need a bit of modification. )

\$\endgroup\$
2
  • \$\begingroup\$ If you want to have the commented code in your answer that's fine, but you do need the golfed down code somewhere, too. \$\endgroup\$
    – Pavel
    Commented Jul 29, 2017 at 5:42
  • \$\begingroup\$ @Phoenix Thanks. Done. \$\endgroup\$
    – Joel Rees
    Commented Aug 1, 2017 at 1:30

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.