20
\$\begingroup\$

This is code golf. For this challenge, I will accept a method (you don't need a full program), but the method signature does count towards the byte count and I want to see the full signature (not a lamdba). The input for the method is an integer array with 81 elements. The output/return value from the method is a string that represents the array as an ascii sudoku board.

If you're using an esoteric language or something that absolutely doesn't have methods, you can adapt, but if the language supports this at all I want to see something might actually be plugged into a "real" ungolfed program, even if the method body itself is a pain to work with. The requirement is not meant to block languages like Jelly or 05AB1E, but to make it easier for languages like Java to build something that makes sense for that platform.

For the input, integer values 1-9 should have obvious meanings. A 0 should always be interpreted as a blank cell. You may also interpret anything else outside the 1-9 range as a blank cell, but this is not required. Positioning from the array to the puzzle starts at the top left and fills each row from left to right before moving to the next row.

For the boxes, I want double lines around the outside and between each 3x3 region, and single lines between other cells. These should be drawn with line drawing characters (if your I/O format represents strings as a sequence of bytes rather than a sequence of characters, you should represent them in a well-known encoding such as UTF-8 or codepage 347).

For this challenge, I am NOT asking you to generate the sudoku puzzle. That is the input for the function. I am NOT asking you to solve the puzzle. I'm just asking you to produce a string to "draw" what you're given (in as few bytes as possible).

Example Input:

Values for the array:

{ 8, 5, 0, 0, 0, 2, 4, 0, 0, 7, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 2, 3, 0, 5, 0, 0, 0, 9, 0, 0 ,0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 7, 0, 0, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 0, 4, 0}

The values can use whatever mechanism is natural for your language: int[], ArrayList, sequence, tuple, string of digits, whatever, as long as you have a value in the input for every cell (no maps for only populated cells to positions). Remember that the input is supplied... it is not part of your byte count. But the input might represent any sudoku puzzle, and the puzzle might not even have a valid solution. You do get to assume that puzzle is printable. You won't get something with 82 elements, for example.

You also get to assume a reasonable fixed-width font.

Corresponding Output:

╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗
║ 8 │ 5 │   ║   │   │ 2 ║ 4 │   │   ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║ 7 │ 2 │   ║   │   │   ║   │   │ 9 ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║   │   │ 4 ║   │   │   ║   │   │   ║
╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣
║   │   │   ║ 1 │   │ 7 ║   │   │ 2 ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║ 3 │   │ 5 ║   │   │   ║ 9 │   │   ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║   │ 4 │   ║   │   │   ║   │   │   ║
╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣
║   │   │   ║   │ 8 │   ║   │ 7 │   ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║   │ 1 │ 7 ║   │   │   ║   │   │   ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║   │   │   ║   │ 3 │ 6 ║   │ 4 │   ║
╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝
\$\endgroup\$
5
  • 4
    \$\begingroup\$ Are you sure about the method part? That doesn't make sense for a lot of languages (i.e., languages without methods). \$\endgroup\$
    – Cyoce
    Jun 16, 2017 at 16:30
  • 1
    \$\begingroup\$ For languages that don't have methods, you can adapt. But if they do, I'm looking for something that might actually be useful to plug into a "real" program. I'll add that to question. \$\endgroup\$ Jun 16, 2017 at 16:32
  • 2
    \$\begingroup\$ What's the reasoning for not allowing lambdas? Those could certainly be plugged into a "real" program just as well as named functions / methods \$\endgroup\$ Jun 16, 2017 at 19:05
  • 2
    \$\begingroup\$ Nitpicky but important: There's no such thing as an "ASCII box drawing character." ASCII covers codes 0 through 127, none of which are box drawing characters. In recent times, Unicode is the standard, but it has several different encodings: UTF-8, UTF-16 etc, all of which use more than 1 byte per boxdrawing character. Older encodings such as Codepage 437 support single-byte box drawing characters. When you use characters outside the ASCII range, you should specify which encodings are valid. en.wikipedia.org/wiki/Box-drawing_character en.wikipedia.org/wiki/Unicode \$\endgroup\$ Jun 16, 2017 at 21:02
  • 2
    \$\begingroup\$ "Method" should probably be "named function" to get the closest possible equivalent to a method in non-object-oriented languages. (For example, C, a widely used language, doesn't have methods but does have named functions.) In most of the languages I'm aware of which have methods, they're that language's equivalent of a named function. (The best-known exception I'm aware of is C++, where using a named function would be a lot more plausible for this task than using a method would be, as it's really unclear what sort of object you'd associate the method with.) \$\endgroup\$
    – user62131
    Jun 17, 2017 at 0:58

14 Answers 14

10
\$\begingroup\$

Python 3, 232 bytes

Thanks to those who helped to golf this down.

Encryption within encryption...

q=lambda x,y:x+y+x+y+x
r=lambda a,b,c,d,e:a+q(q(b*3,c),d)+e+"\n"
print(((r(*"╔═╤╦╗")+q(q("║ %d │ %d │ %d "*3+"║\n",r(*"╟─┼╫╢")),r(*"╠═╪╬╣"))+r(*"╚═╧╩╝"))%eval(input())).replace(*"0 "))

Try it online!

To be golfed.

\$\endgroup\$
4
  • \$\begingroup\$ How did I not notice that... that's like the entire reason why I used Python 2, but thanks. \$\endgroup\$
    – Leaky Nun
    Jun 16, 2017 at 16:35
  • 1
    \$\begingroup\$ Actually you're better off using Python 3 since then you won't need the first line. \$\endgroup\$ Jun 16, 2017 at 16:36
  • 1
    \$\begingroup\$ You can remove more parens on the last line: tio \$\endgroup\$ Jun 16, 2017 at 16:37
  • \$\begingroup\$ Remove definition of f and define i as i=["╔"+(g+"╦")*2+g+"╗"]+d+2*(["╠"+(e+"╬")*2+e+"╣"]+d)+["╚"+(h+"╩")*2+h+"╝"] saves 4 bytes \$\endgroup\$ Jun 16, 2017 at 16:41
8
\$\begingroup\$

C (gcc), 398 395 291 bytes

Saved 3 bytes by working through the string reversed, and 104 (!) bytes thanks to Leaky Nun.

#include<locale.h>
#define q(x,y) x y x y x
#define D L"╝"q(q("═══","╧"),"╩")"╚"q(q("\n║"q(q(" & ","│"),"║")"║","\n╢"q(q("───","┼"),"╫")"╟"),"\n╣"q(q("═══","╪"),"╬")"╠")"\n╗"q(q("═══","╤"),"╦")"╔"
i;f(int*t){setlocale(LC_ALL,"");for(i=721;i--;)wprintf(L"%lc",D[i]%19?D[i]:*t++?48+t[-1]:32);}

Try it online!

C (gcc), 395 bytes

I'll keep this here so its more evident as to how the program works.

#include<locale.h>
#define A L"\n╢───┼───┼───╫───┼───┼───╫───┼───┼───╟"
#define B L"\n║ & │ & │ & ║ & │ & │ & ║ & │ & │ & ║"
#define C L"\n╣═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╠"
#define E B A B A B
#define D L"╝═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╚"E C E C E L"\n╗═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╔"
i;f(int*t){setlocale(LC_ALL,"");for(i=721;i--;)wprintf(L"%lc",D[i]%19?D[i]:*t++?48+t[-1]:32);}

Try it online!

Working with unicode in C is... costly. Takes input as an int* as shown in the link and in the specification.

I'm going to see if I can save bytes using some number magic instead of hardcoding the string.

\$\endgroup\$
3
  • \$\begingroup\$ 355 bytes \$\endgroup\$
    – Leaky Nun
    Jun 16, 2017 at 19:04
  • \$\begingroup\$ @LeakyNun Huh, thanks! It's 291 bytes according to TIO \$\endgroup\$ Jun 16, 2017 at 19:10
  • \$\begingroup\$ TIO is counting using SBCS. \$\endgroup\$
    – Leaky Nun
    Jun 16, 2017 at 19:12
7
\$\begingroup\$

PHP, 297 bytes

<?for(;$l<19;$l++)echo$l&1?strtr(vsprintf(str_pad("",67,"║ %d │ %d │ %d "),array_slice($_GET,9*($l/2^0)-9,9)),0," "):str_pad([╔,╟,╠,╚][$b=$l?$l<18?$l%6<1?2:1:3:0],108,strtr("11101110111".[╦,╫,╬,╩][$b],[[╤,═],[┼,─],[╪,═],[╧,═]][$b])).[╗,╢,╣,╝][$b],"
";

Try it online!

Expanded

for(;$l<19;$l++)  # loop thrpugh lines
  echo$l&1 # Output
    ?strtr(
        vsprintf(str_pad("",67,"║ %d │ %d │ %d ") # formated string for lines with numbers
        ,array_slice($_GET,9*($l/2^0)-9,9)) # nine items of the input array
      ,0," ") #replace zeros with space
    :str_pad([╔,╟,╠,╚][$b=$l?$l<18?$l%6<1?2:1:3:0] # start character non number lines and switch number four cases
      ,108 # fill too 108 bytes
      ,strtr("11101110111".[╦,╫,╬,╩][$b] # with string 
        ,[[╤,═],[┼,─],[╪,═],[╧,═]][$b]))  #replace ones and zero with the two character in array chosed 
    .[╗,╢,╣,╝][$b] # end row with chosen character
  ,"
    "; # end line with new line

used functions for both versions

vsprintf , strtr , str_pad , array_slice , array_chunk

PHP, 313 bytes

<?$r=($s=str_pad)(╔,108,($t=strtr)(($p=11101110111).╦,[╤,═])).╗;foreach(array_chunk($_GET,9)as$v)$r.=$t(vsprintf($s("
",68,"║ %d │ %d │ %d "),$v),0," ").(++$k%9?$k%3?$s("
╟",109,$t($p.╫,[┼,─])).╢:$s("
╠",109,$t($p.╬,[╪,═])).╣:"");echo$r.$s("
╚",109,$t($p.╩,[╧,═])).╝;

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ How does this work? \$\endgroup\$
    – Cyoce
    Jun 16, 2017 at 19:39
  • \$\begingroup\$ @Cyoce I have added an explanation for my new version \$\endgroup\$ Jun 16, 2017 at 22:00
5
\$\begingroup\$

T-SQL, 445 437 bytes (in 381 characters)

DECLARE @r INT=0,@ NVARCHAR(999)=N'╔=╤=╤=╦=╤=╤=╦=╤=╤=╗P'p:SELECT @+=FORMAT(CAST(SUBSTRING(a,@r*9+1,9)AS INT),N'║ 0 │ 0 │ 0 ║ 0 │ 0 │ 0 ║ 0 │ 0 │ 0 ║P')FROM t
SET @r+=1IF @r=9SET @+=N'╚=╧=╧=╩=╧=╧=╩=╧=╧=╝P'ELSE IF @r%3=0SET @+=N'╠=╪=╪=╬=╪=╪=╬=╪=╪=╣P'ELSE SET @+=N'╟-┼-┼-╫-┼-┼-╫-┼-┼-╢P'IF @r<9GOTO p
PRINT REPLACE(REPLACE(REPLACE(REPLACE(@,'=',N'═══'),'-',N'───'),'0',' '),'P',CHAR(13))

Input is via a string of digits stored in column a of pre-existing table t, per approved methods.

Format and Explanation:

DECLARE @r INT=0, @ NVARCHAR(999)= N'╔=╤=╤=╦=╤=╤=╦=╤=╤=╗P'
p:
    SELECT @+= FORMAT(CAST(SUBSTRING(a, @r*9+1, 9) AS INT),
        N'║ 0 │ 0 │ 0 ║ 0 │ 0 │ 0 ║ 0 │ 0 │ 0 ║P') FROM t
    SET @r+=1
    IF @r=9 SET @+= N'╚=╧=╧=╩=╧=╧=╩=╧=╧=╝P'
    ELSE IF @r%3=0 SET @+= N'╠=╪=╪=╬=╪=╪=╬=╪=╪=╣P'
    ELSE SET @+= N'╟-┼-┼-╫-┼-┼-╫-┼-┼-╢P'
IF @r<9 GOTO p
PRINT REPLACE(REPLACE(REPLACE(REPLACE(@, '=',N'═══'), '-',N'───'), '0',' '), 'P',CHAR(13))

In the top line of the loop I'm getting the next 9 digits of the input string from column a of pre-existing table t.

I convert that string of digits to an integer, and use the .Net FORMAT function to display them using a custom text template '║ 0 │ 0 │ 0 ║ 0 │ 0 │ 0 ║ 0 │ 0 │ 0 ║P'.

After that I just append the appropriate divider line, and make some byte-saving replacements before output.

Output is displayed in the results pane:

╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗
║ 8 │ 5 │   ║   │   │ 2 ║ 4 │   │   ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║ 7 │ 2 │   ║   │   │   ║   │   │ 9 ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║   │   │ 4 ║   │   │   ║   │   │   ║
╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣
║   │   │   ║ 1 │   │ 7 ║   │   │ 2 ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║ 3 │   │ 5 ║   │   │   ║ 9 │   │   ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║   │ 4 │   ║   │   │   ║   │   │   ║
╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣
║   │   │   ║   │ 8 │   ║   │ 7 │   ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║   │ 1 │ 7 ║   │   │   ║   │   │   ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║   │   │   ║   │ 3 │ 6 ║   │ 4 │   ║
╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝

I previously had some additional replacements for some of the other drawing characters, but they ultimately didn't save me bytes.

EDIT 1: Saved 8 bytes by starting @r at zero instead of 1, and removing some unneeded spaces.

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

Retina, 196 167 bytes

.{27}
¶N#=XZ#Q¶|$&
\d{9}\B
$&¶M#─┼Y#P¶|
\d{3}
 $& |
\B\d
 │ $&
^¶.*
B#=RT#E
$
¶H#=UW#K
+`#([^#¶]+)([^#¶])#
#$1#$2#$1#$2#$1#
#(.)#
$1$1$1
T`0=|#L` ═-╬

Try it online! Takes input as a string of length 81. Explanation: Because the box drawing characters cost three bytes, the unicode code points ═-╬ are represented in the code using =|#A-Z (not all the characters are used but sticking to ranges saves bytes). Additionally the rows are compressed using # signs: a#bcd#e expands to abbbcbbbcbbbdbbbcbbbcbbbdbbbcbbbcbbbe.

.{27}
¶N#=XZ#Q¶|$&

Inserts ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ for every third row, plus a at the start of every group of 27.

\d{9}\B
$&¶M#─┼Y#P¶|

Inserts ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ between the other rows, plus s at the start of those rows.

\d{3}
 $& |

Inserts s after every three digits. All the s have now been inserted.

\B\d
 │ $&

Inserts |s between all the remaining pairs of digits. (This one is the actual box drawing character rather than a pipe. Unfortunately the characters ─│┼ have codes too far apart from each other and the double box characters to make it worth while using placeholders.)

^¶.*
B#=RT#E

Changes the first row to ╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗ (this saves 1 byte over not adding the first row in the first place).

$
¶H#=UW#K

Adds ╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝ after the last row.

+`#([^#¶]+)([^#¶])#
#$1#$2#$1#$2#$1#

Expands a#bcd#e, first to a#bc#d#bc#d#bc#e, then to a#b#c#b#c#b#d#b#c#b#c#b#d#b#c#b#c#b#e.

#(.)#
$1$1$1

Changes #b# to bbb. This completes the decompression.

T`0=|#L` ═-╬

Deletes all the zero entries, and replaces the placeholders with the box drawing characters.

\$\endgroup\$
4
  • \$\begingroup\$ You forgot to replace 0 by space. \$\endgroup\$
    – Leaky Nun
    Jun 16, 2017 at 18:54
  • \$\begingroup\$ Also has double lines around every row, rather than just the border and 3x3 regions. \$\endgroup\$ Jun 16, 2017 at 18:54
  • \$\begingroup\$ @JoelCoehoorn Fixed, sorry. \$\endgroup\$
    – Neil
    Jun 16, 2017 at 19:10
  • \$\begingroup\$ @LeakyNun Thanks, I'd overlooked that. (Also, I like to avoid lines ending with, or especially only containing, spaces, which is why I looked for an alternative 2-byte saving.) \$\endgroup\$
    – Neil
    Jun 16, 2017 at 19:11
4
\$\begingroup\$

JavaScript (ES6), 246 bytes / 198 chars

(n,r=(x,y)=>x+y+x+y+x,q=s=>([u,w,x,y,z]=[...s[0]],u+r(r(w+w+w,x),y)+z+`
`))=>q`╔═╤╦╗`+n.reduce((o,v,i)=>o+"║││"[i++%3]+` ${v||" "} `+(i%9?e:`║
`+(i-27&&i-54?i<81?q`╟─┼╫╢`:e:q`╠═╪╬╣`)),e="")+q`╚═╧╩╝`

Input is an array of integers. Ended up using the same two helper functions as Leaky Nun's Python answer, so credit goes there.

If function is required, 263 bytes / 215 chars

function g(n,r=(x,y)=>x+y+x+y+x,q=s=>([u,w,x,y,z]=[...s[0]],u+r(r(w+w+w,x),y)+z+`
`)){return q`╔═╤╦╗`+n.reduce((o,v,i)=>o+"║││"[i++%3]+` ${v||" "} `+(i%9?e:`║
`+(i-27&&i-54?i<81?q`╟─┼╫╢`:e:q`╠═╪╬╣`)),e="")+q`╚═╧╩╝`}

Test Snippet

Any input of 81 numbers is supported (1234, 1, 2, 3, 4. [1 2 3 4], etc). Best viewed as full page.

f=
(n,r=(x,y)=>x+y+x+y+x,q=s=>([u,w,x,y,z]=[...s[0]],u+r(r(w+w+w,x),y)+z+`
`))=>q`╔═╤╦╗`+n.reduce((o,v,i)=>o+"║││"[i++%3]+` ${v||" "} `+(i%9?e:`║
`+(i-27&&i-54?i<81?q`╟─┼╫╢`:e:q`╠═╪╬╣`)),e="")+q`╚═╧╩╝`

onload=I.oninput=_=>O.innerHTML=(m=I.value.match(/\d/g))&&m.length==81?f(m.map(x=>+x)):''
<textarea id=I rows=3 style="width:95%">8, 5, 0, 0, 0, 2, 4, 0, 0, 7, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 2, 3, 0, 5, 0, 0, 0, 9, 0, 0 ,0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 7, 0, 0, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 0, 4, 0</textarea>
<pre id=O>

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

SOGL V0.12, 174 172 164 160 158 bytes

«ž#>]Wž²6√±_ΕΨ╥╬]v←ē⅓ZΗ⌡z∫◄‽q   §↑╗∑Ολ[Μ↕z↓/∆Yn⁄:Ο║χ≥¾▓g*≈]═+π℮─6⁽SE/⁷,0+►Ƨ⌡u\^⁄-▼0cΦ“╤─┼╬│║═╔╗╚╝”Φ⅜nΡ¡ΞΨīŗ(`½│uģ“ ╬ζ─{ζ} 6Δ¹∑A'⁄─{IaW}¹∑#¶ŗ3 ¶ŗ ”+Ƨøp+!!┌d0@ŗčŗ

Overly long explanation:

...“                          push a big base-43 encoded number; will be used later. It's pushed here to save a byte on a quote
    ...”                      push "╤─┼╬│║═╔╗╚╝" - the chars in SOGLs encoding
        ...“                  push 679301851737965572513837476350078477
             ╬                push "╬"
              ζ               convert it to its codepoint (9580)
               ─              convert that number to an array of base-9580 numbers
                {ζ}           convert each number to a character (pushing each on the stack)
                    6Δ        push all ascii chars up to 6 (" !"#$%&'()*+,-./0123456")
                      ¹∑      join all the strings on the stack together ("╤─┼╬│║═╔╗╚╝╦╟╫╢╠╪╣╧╩ !"#$%&'()*+,-./0123456")
                        A     save on variable `A`. Now ontop of the stack is the 1st big number
                         '⁄─  onvert from base 43

{   }                           for each number do
 I                                increase
  aW                              get its position in the variable A
     ¹∑                         join all the strings ontop of the stack (the loop above pushed each char separately)
       #¶ŗ                      replace quote (") characters with newlines
          3 ¶ŗ                  replace 3s with "¶"
               ”+               append "”"
                 Ƨøp+           append "øp"
                     !!         execute the created code as SOGL
                       ┌        push "-"
                        d       push variable d - defaults to string input. In a full program could be set as an input
                         0@ŗ    replace zeroes with spaces
                            č   chop into an array
                             ŗ  replace ["-" with input chopped - so each iteratively]

The program that's executed:

───!#
 - $
¶%&¶'(
)╪)╪)+
)╤)╤),
)╧)╧).
┼#
+╬+/
0!╫0!1
,╦,2
.╩.4
5│$║&
#0
═══)
$│$5
║&&%
╠/╬+╣6'*
╟1╫0!╢(
(6
╔2╦,╗6'**╚4╩.╝”øp

where all but last line are just in the entire program replace occurrences of the last char of this line with the rest of this line. This is the reason it was possible to make half of the chars just random ascii (but getting so that spaces, dashes, and quotes are usefully used took a while to figure out)

...”    push the whole sudoku grid
    øp  print nothing (prevents bug that this code would already print and pop the result)

Try it Here!
The online interpreter code is more correct because tabs don't work with SE

-8 bytes: brute force replacement compressing the entire board, then replacing foreign chars (to the codepage) with their codepoints. Doing this took an hour less than the old program...
-4 bytes: compressing the compressed string...
-2 bytes: using a variable+string instead of array

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

Batch, 332 bytes

@echo off
set/ps=
set s=%s:0= %
call:l É Í Ñ Ë »
set t="Ç Ä Å × ¶"
for %%i in (%t% %t% "Ì Í Ø Î ¹" %t% %t% "Ì Í Ø Î ¹" %t% %t% "È Í Ï Ê ¼")do call:c %%~i
exit/b
:c
set t=º
for %%j in (³ ³ º ³ ³ º ³ ³ º)do call set t=%%t%% %%s:~,1%% %%j&call set s=%%s:~1%%
echo %t%
:l
set t=%2%2%2%3%2%2%2%3%2%2%2
echo %1%t%%4%t%%4%t%%5

Needs the console to be in CP437. If that's not your default, then you can change it using the CHCP 437 command if your console is set to TrueType fonts. (It will only work with raster fonts if CP437 is already your default code page.) This is what the code looks like in CP437:

@echo off
set/ps=
set s=%s:0= %
call:l ╔ ═ ╤ ╦ ╗
set t="╟ ─ ┼ ╫ ╢"
for %%i in (%t% %t% "╠ ═ ╪ ╬ ╣" %t% %t% "╠ ═ ╪ ╬ ╣" %t% %t% "╚ ═ ╧ ╩ ╝")do call:c %%~i
exit/b
:c
set t=║
for %%j in (│ │ ║ │ │ ║ │ │ ║)do call set t=%%t%% %%s:~,1%% %%j&call set s=%%s:~1%%
echo %t%
:l
set t=%2%2%2%3%2%2%2%3%2%2%2
echo %1%t%%4%t%%4%t%%5
\$\endgroup\$
2
\$\begingroup\$

With ideas harvested from other answers:

C# (.NET Core), 401 bytes, 349 Chars

string s(string x){Func<string,string,string>q=(m,n)=>m+n+m+n+m;var a="╔"+q(q("=","╤"),"╦")+"╗";for(var i=0;i<9;) {a+=int.Parse(x.Substring(i*9,9)).ToString("\n║"+q(q(" 0 ","│"),"║")+"║\n")+(i++<8?(i%3>0?"╟"+q(q("-","┼"),"╫")+"╢":"╠"+q(q("=","╪"),"╬")+"╣"):"╚"+q(q("=","╧"),"╩")+"╝");}return a.Replace("=","═══").Replace("-","───").Replace("0"," ");}

Ungolfed:

static public string s(string x)
{
    Func<string,string,string>q=(m,n)=>m+n+m+n+m;
    var a="╔"+q(q("=","╤"),"╦")+"╗";
    for (var i=0;i<9;) //once per row
    {
        //parse that row to an int, then spit out a formatted string
        a += int.Parse(x.Substring(i*9,9)).ToString("\n║"+q(q(" 0 ","│"),"║")+"║\n") 
          // as well as a trailing row for the box
          + (i++<8?(i%3>0?"╟"+q(q("-","┼"),"╫")+"╢":"╠"+q(q("=","╪"),"╬")+"╣"):"╚"+q(q("=","╧"),"╩")+"╝");
    }
    //expand placeholder characters before returning
    return a.Replace("=","═══").Replace("-","───").Replace("0"," ");
}

Try it online!

My Answer:

C# (.NET Core), 509 430 418 bytes, 328 chars

string b(string x){var a="╔=╤=╤=╦=╤=╤=╦=╤=╤=╗\n║";for(int i=0,j=0,k,l,m;j<3;j++)for(k=0;k<3;k++){for(l=0;l<3;l++)for(m=0;m<3;)a+=" "+x[i++]+(m++<2?" │":" ║");a+=i<80?(k<2?"\n╟-┼-┼-╫-┼-┼-╫-┼-┼-╢\n║":"\n╠=╪=╪=╬=╪=╪=╬=╪=╪=╣\n║"):"\n╚=╧=╧=╩=╧=╧=╩=╧=╧=╝";}return a.Replace("=","═══").Replace("-","───").Replace("0"," ");}

Ungolfed:

public string s(string x)
{
    var a = "╔=╤=╤=╦=╤=╤=╦=╤=╤=╗\n║";
    for (int i=0,j=0,k,l,m;j<3;j++)
    {
        for (k = 0; k < 3;k++)
        {
            for (l = 0; l < 3; l++)
            {
                for (m = 0; m < 3;)
                    a += " " + x[i++] + (m++ < 2 ? " │" : " ║");
            }
            a += i < 80 ? (k < 2 ? "\n╟-┼-┼-╫-┼-┼-╫-┼-┼-╢\n║": "\n╠=╪=╪=╬=╪=╪=╬=╪=╪=╣\n║") 
                        : "\n╚=╧=╧=╩=╧=╧=╩=╧=╧=╝";
        }
    }
    return a.Replace("=", "═══").Replace("-","───").Replace("0"," ");
}

I also looked at using a lambda for the `for` loops here, but it actually cost me one byte (saved 10 bytes per loop, with 41 bytes of overhead).

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ Do you need to count each drawing character as two bytes? \$\endgroup\$
    – BradC
    Jun 16, 2017 at 21:09
  • \$\begingroup\$ I did, fixed now. I had meant to address that in question and count characters rather than bytes, because of those characters, but I suppose it's too late now. \$\endgroup\$ Jun 16, 2017 at 21:13
  • \$\begingroup\$ Yep, bytes is harder, some ascii substitutions save bytes but don't impact characters (or even hurt characters). I'm working on T-SQL, and char vs nchar is a pretty big difference. \$\endgroup\$
    – BradC
    Jun 16, 2017 at 21:17
1
\$\begingroup\$

Chip, 3645 bytes

...that's not a typo...

ooooooZZ-)-K-)-K-)-K-)-K-)-K-)-K-)-K-)-K-)-K-)-K-)-K-).
|`xxxx-x--(x---x---x---x---x-v-x---x---x---x---x---x-.`K-)-K-)-K-)-K-).
|b|`xx-x--(x-v-x---x-v-x---x-x-x---x-v-x---x-v-x---x-x-x---x-v-x---x-.`K-).
|>xd`x-x(v-x-x-x-v-x-x-x-v-x-x-x-v-x-x-x-v-x-x-x-v-x-x-x-v-x-x-x-v-x-x-x-.|
||`--x-x-x(x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x/.
|`--z',/\',/\',/\',/\',/\',/\',/\',/\',/\',/\',/\',/\',/\',/\',/\',/\',/\','
`-. |,< >.| >.| >.| >.| >.| >.| >.| >.| >.| >.| >.| >.| >.| >.| >.| >.| >.|
*-x-/xZ/xZ^/xZ^/xZ^/xZ^/xZ^/xZ^/xZ^/xZ^/xZ^/xZ^/xZ^/xZ^/xZ^/xZ^/xZ^/xZ^/xZ'
Z~' |`'|`' |`' |`' |`' |`' |`' |`' |`' |`' |`' |`' |`' |`' |`' |`' |`','`'
    `)-K-)-K-)-K-)-K-)-K-)-K-)-K-)-K-)-K-)-K-)-K-)-K-)-K-)-K-)-K-)-K-)'
=
oooooo).h
`)))--^M^Zh
=
oooooo
|    `(--------------------------------------------------------------------------------------------------------va
KZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ^cg
)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx-xKZvvZ
xxxxxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxxx-Kxxxx}e
)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)x))xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)x))xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)x)b`feac
  c
=
oooooo
,'   `(--------------------------------------------------------------------------------------------------------.cba
KZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ^x^^)v--.
xx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxxx-xK-'f e`.
)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx-x-K-+Z+Z}e
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxK^}b gac
xxxxxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxxx-K^d
=
oooooo
,-'
KZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZtabgfv------.
)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx-xK^^x-Zv-vZ}e
xxxxxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxxxK^---^}cade,]b
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)-K----^-^^~'
,v'
db
=
oooooo
,--' `(--------------------------------------------------------------------------------------------------------v-.,-v-ZZZZZZZZZZZZf
KZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ'a{x.df
)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xx)xxKx-xxv+Zc
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)x-KZx+bge
xx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxx)xxxxxxxxxxxx---K\--^c
 a^b
=
oooooo
,---'`(--------------------------------------------------.
KZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ'gf
)xxxxx)xxxxx)xxxxx)xxxxx)xxxxx)xxxxx)xxxxx)xxxxx)xxxxx)xx-^KZc
)xxxxx)x)xxx)x)xxx)xxxxx)x)xxx)x)xxx)xxxxx)x)xxx)x)xxx)xxbahKZ\ZZZ
x))xxxxxxxxxxxxxxxx))xxxxxxxxxxxxxxxx))xxxxxxxxxxxxxxxx))-K-eh|fff
 ,--K-v-v-K--v-vK-v---K-----K-----K-----K-----K-----K `--Z-Z--'
A/ab/B/e/C/cd/D/-e/A
*}s

Try it online!, sort of. The TIO version contains a cutoff about a third of the way in (the t after the 4th oooooo), so that it should terminate in less than 60 seconds. The full version takes about 1m25s on my machine, and TIO seems about half as quick. This also means the TIO only shows the first 7 lines of output.

My first draft weighed in at a massive 19758 bytes, and took me about 8m30s to run. The final solution, pre-golfing, was a spry 5980 bytes, taking only 2m07s.

So, how's it work, then?

This takes a string of 82 bytes, 81 digits, followed by a terminator. \0 or \n or even another number will do. (This implementation actually only looks at the first 81, but requires at least one more, since Chip will terminate if it has exhausted its input. If this is unacceptable, the flag -z may be used, which effectively appends an infinite number of \0 bytes to the end of the input.) The shortened TIO code doesn't actually get to all 81 bytes, so the point is moot there.

The way I've implemented this, it only looks at the low 4 bits of the input, so anything, really, can be a sudoku 'puzzle', from raw binary data, to the lesser-known works of Shakespeare. Any character whose low 4 bits are all zero will appear as a space (a special case), all other characters map into 123456789:;<=>?. (So, the last few aren't digits, but neither is 10 a valid number in normal sudoku).

For the box-drawing characters, it produces UTF-8, equating to 3 bytes each.

What about the actual implementation?

Chip is a 3D language that is inspired by integrated circuits. It has wires, logic gates, and memory cells. Most stuff is done on 2D planes, but these planes may be stacked atop one another. That is how this program is built.

The lines that start with = are the layer separators. Then, the layers are stacked, with the top and left sides aligned. The o's serve as pins, allowing signals to pass from one layer to another.

Each layer here has a purpose, you could think of them as functions. The first layer controls everything; it 'calls' each of the other layers in turn. There is a repeating left-to-right pattern here. That pattern keeps track of which of the 19 lines of output we are currently printing.

The second layer is rather tiny, and it has a very tiny job. It sets the 0x80 bit for all the lines of output except the lines that contain numbers. h is the Chip element that corresponds to the 0x80 bit. (The low end of the alphabet h through a define all eight output bits.)

Layer three is where we really get into the meat of printing. This layer is in charge of line one. The ungolfed version has eight rows of x's and )'s, mapping to 0's and 1's for each of the eight bits of each byte. However, we can take advantage of the patterns in the bits to accomplish the same task in fewer rows.

Layer four is much like the third. It handles the horizontal double lines.

Layer five handles the last line. Note that it is missing the wire along the top that the other layers have. This is because we don't need to return control to the sequencer. Instead, we can just terminate execution here with t.

Layer six handles the horizontal single lines.

Layer seven is where the numbers are printed. It is 'called' for each the nine numeric lines. It consumes 9 bytes of input as part of its execution.

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

JavaScript (ES6), 222 bytes

Using short syntax for ES6 functions - 174 chars encoded in utf8, 222 bytes (https://mothereff.in/byte-counter). Using function ... requires 16 more bytes.

F=v=>[1,...v].map((x,i)=>'│║│'[i%3]+` ${x||' '} `+(i%9?'':`║
${[h,r,s,u,t]=i%27?'─╟╫┼╢':i>80?'═╚╩╧╝':i?'═╠╬╪╣':'═╔╦╤╗',r+(s=(u=(h+=h+h)+u+h+u+h)+s)+s+u+t}
`)).join``.slice(6)

Less golfed

F=v=>{
   // horizontal lines are appended after each 9th element
   // so I need to prepend a dummy first element to draw the top horizontal line
   v = [1, ...v];
   return v.map( (x,i) => 
     '│║│'[i % 3] + ` ${x||' '} ` // left bar and cell value
     + ( i % 9 ? '' // add horizontal line after each 9th element
       // the line drawing characters are chosen according to the value of i
       : `║\n${ [h, r, s, u, t] = 
         i % 27 != 0
         ? '─╟╫┼╢'
         : i > 80 
           ? '═╚╩╧╝' // i==81, bottom row
           : i != 0
             ? '═╠╬╪╣'
             : '═╔╦╤╗', // i==0, top row
         r + (s = (u = (h += h + h) + u + h + u + h) + s) + s + u + t
         }\n`
       )
   ).join``
   .slice(6) // cut the first cell (the dummy element)
}

F=v=>[1,...v].map((x,i)=>'│║│'[i%3]+` ${x||' '} `+(i%9?'':`║
${[h,r,s,u,t]=i%27?'─╟╫┼╢':i>80?'═╚╩╧╝':i?'═╠╬╪╣':'═╔╦╤╗',r+(s=(u=(h+=h+h)+u+h+u+h)+s)+s+u+t}
`)).join``.slice(6)

function go() {
  var i=I.value
  i = i.match(/\d+/g).map(x => +x); // convert strings to numbers
  O.textContent = F(i)
}
#I { width: 90% }
<input id=I value='8 5 0 0 0 2 4 0 0 7 2 0 0 0 0 0 0 9 0 0 4 0 0 0 0 0 0 0 0 0 1 0 7 0 0 2 3 0 5 0 0 0 9 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 8 0 0 7 0 0 1 7 0 0 0 0 0 0 0 0 0 0 3 6 0 4 0'>
<button onclick='go()'>go</button>
<pre id=O></pre>

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

Java (OpenJDK 8), 279 bytes

String f(int[]a){String P="0121213121213121214",R[]={"╔═╤╦╗","║ │║║x","╟─┼╫╢","╠═╪╬╣","╚═╧╩╝"},r="";for(int X:P.getBytes()){for(int x:P.replace("1",R[X-=48].length()>5?"151":"111").getBytes())r+=R[X].charAt(x-48);r+="\n";}for(int i:a)r=r.replaceFirst("x",i>0?""+i:" ");return r;}

Try it online!

For the byte count, use CP-437, which is natively supported by Java as IBM437 (recent APIs) or Cp437 (older APIs); so use a system that has this charset has this charset as default charset.

This code is compatible from Java 5 onwards, but was tested on Java 8 only.

Explanation

String f(int[]a){
  String P="0121213121213121214",                         // Both lines and rows are repeated according to this pattern.
         R[]={"╔═╤╦╗","║ │║║x","╟─┼╫╢","╠═╪╬╣","╚═╧╩╝"},  // Characters found on each line.
                                                          //   (note the 'x')
         r="";                                            // The string under construction
  for (int X: P.getBytes()) {                             // For each line,
    for (int x:                                           //  For each character in the pattern,
         P.replace("1",R[X-=48].length()>5?"151":"111")   //    *but* with a cell width of 3,
                                                          //    and with an optional character ('x')
         .getBytes())
      r+=R[X].charAt(x-48);                               //   append the real mapped character
    r+="\n";                                              //  then append a new line
  }
  for(int i:a)                                            // For each number in the input
    r = r.replaceFirst("x",i>0?""+i:" ");                 //  replace the first 'x' with that number.
                                                          //    (or space if zero)
  return r;                                               // Return the constructed string.
}
\$\endgroup\$
1
\$\begingroup\$

Tcl, 373 bytes (273 chars)

Very naïve approach, but I just had to do it even it not being a winner by any measure:

puts ╔[set D ═══]╤$D╤$D╦$D╤$D╤$D╦$D╤$D╤$D╗
set r ║ 
lmap x $L {set r $r\ [expr $x?$x:{ }]\ [expr [incr i]%3?"│":"║"]
if ![expr $i%9] {puts $r\n[expr $i%27?"╟[set S ───]┼$S┼$S╫$S┼$S┼$S╫$S┼$S┼$S╢":$i<72?"╠$D╪$D╪$D╬$D╪$D╪$D╬$D╪$D╪$D╣":"╚$D╧$D╧$D╩$D╧$D╧$D╩$D╧$D╧$D╝"]
set r ║}}

Try it online!


Same chars expense but more bytes:

Tcl, 421 bytes (273 chars)

puts ╔[set D ═══]╤$D╤$D╦$D╤$D╤$D╦$D╤$D╤$D╗
set r ║ 
lmap x $L {set r $r\ [expr $x?$x:{ }]\ [expr [incr i]%3?"│":"║"]
if ![expr $i%9] {puts $r\n[expr $i%27?"╟───┼───┼───╫───┼───┼───╫───┼───┼───╢":$i<72?"╠$D╪$D╪$D╬$D╪$D╪$D╬$D╪$D╪$D╣":"╚$D╧$D╧$D╩$D╧$D╧$D╩$D╧$D╧$D╝"]
set r ║}}

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ that's 599 UTF-8 bytes. You should try to reuse the common box characters to save bytes \$\endgroup\$
    – dzaima
    Jun 18, 2017 at 21:42
  • \$\begingroup\$ @dzaima:l know, I can do what I did on A keyboard so real you can almost TASTE it \$\endgroup\$
    – sergiol
    Jun 18, 2017 at 21:46
  • \$\begingroup\$ @dzaima: It is why I said Very naïve approach \$\endgroup\$
    – sergiol
    Jun 18, 2017 at 21:49
0
\$\begingroup\$

SlimSharp, 284 characters (bytes not counted)

S b(S x){S a="╔=╤=╤=╦=╤=╤=╦=╤=╤=╗\n║";for(I i=0,j=0,k,l,m;j<3;j++)for(k=0;k<3;k++){for(l=0;l<3;l++)for(m=0;m<3;)a+=" "+x[i++]+(m++<2?" │":" ║");a+=i<80?(k<2?"\n╟-┼-┼-╫-┼-┼-╫-┼-┼-╢\n║":"\n╠=╪=╪=╬=╪=╪=╬=╪=╪=╣\n║"):"\n╚=╧=╧=╩=╧=╧=╩=╧=╧=╝";}return a.R("=","═══").R("-","───").R("0"," ");}

This is a simple adaption of my C# answer.

\$\endgroup\$

Your Answer

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

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