Typesetting multidimensional labels

12

In a steam-punk multidimensional world, our boss wants to affix printed index labels to each drawer in our conglomerate's multidimensional file cabinet.

The boss wants to typeset the entire label sheet as a single form, using a font bought only for this purpose, so we have to order the sorts (metal symbol pieces). Since sorts are very expensive, our order must be for the exact count of each digit-symbol.

For a given (by any means) set of lengths of dimensions ≥ 0, return (by any means) our order, which is the frequency table of digits required to typeset all the Cartesian coordinates. It must be arranged by keyboard order of appearance (i.e. 0 after 9), and may not include orders of 0 sorts, so if no sorts are to be ordered at all (because a dimension has length 0); print nothing.

  • Bonus of -3 sorts if your code can handle (i.e. print nothing) 0 dimensions too.
  • Final newline chars are acceptable.
  • Prohibition on standard loopholes apply.
  • As mentioned, sorts are expensive, this is therefore .

A kind soul may edit this challenge to include automated scoring, so include a header like:
# LanguageName, 123 sorts

Test cases

Given 11, print:

1 4
2 1
3 1
4 1
5 1
6 1
7 1
8 1
9 1
0 1

because the needed labels are 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, and 11.


Given 2 3, print:

1 5
2 5
3 2

because the needed labels are 1 1, 1 2, 1 3, 2 1, 2 2, and 2 3.


Given 2 0, print an empty line:

or nothing.


Given 1 2 3, print:

1 11
2  5
3  2

because the needed labels are 1 1 1, 1 1 2, 1 1 3, 1 2 1, 1 2 2, and 1 2 3


Given 5 5 5 5, print:

1 500
2 500
3 500
4 500
5 500

And no, I'm not going to list all 625 labels.

Adám

Posted 2015-11-08T12:40:54.690

Reputation: 37 779

I'm a little unclear about the output requirements. In the text, it says "return (by any means)", but the rest suggests that a very specific output format is required, and that it needs to be printed. Which one is it? E.g. talking about trailing newlines seems completely redundant if the output format can be anything. – Reto Koradi – 2015-11-08T20:29:27.043

1@RetoKoradi the format has to look more or less as shown, but it may be in an interactive session, a file, a pop-up, STDOUT, etc. Do you have a suggestion as to how I could phrase this to make it clearer? – Adám – 2015-11-08T21:39:05.013

Answers

6

Dyalog APL, 10 7

The code is 10 bytes long and qualifies for the bonus.

Thanks to user46915 for 3 bytes!

,∘≢⌸∊⍕¨∊⍳⎕

Note that (input) doesn't work on TryAPL; you can try the function form here.

            ⎕      Get input
           ⍳       Index vector
       ∊⍕¨∊        Flatten, stringify, flatten again
      ⌸            From the key, display the
{⍺,  }             elements concatenated with the
   ≢⍵              number of times they occur

I don't completely understand the operator, but {⍺}⌸ lists the unique values taken on, and {⍵}⌸ lists their places in the argument.

This has the correct ordering because it is the order in which digits appear in the multidimensional array of labels.

lirtosiast

Posted 2015-11-08T12:40:54.690

Reputation: 20 331

1

Yup, that's the solution I had in mind. This may help understanding the Key operator.

– Adám – 2015-11-08T18:42:38.287

1Doesn't APL always win at codegolf? – vy32 – 2015-11-09T03:59:54.667

@vy32 No. APL may be the most concise general purpose language, But there will always be domain-specific languages that are better at a certain limited domain than any general purpose language. Within the specific domain of code-golfing, golfing languages like Pyth and CJam usually win. However, it is remarkable that APL, being a commercial language used in production by very large companies, comes even close. Also, for the price of being slightly more verbose, it is probably easier for humans to learn to read APL than golfing languages. – Adám – 2015-11-09T12:10:30.590

Wait, so you mean I can make whole histogram simply with ,∘≢⌸ without any outer products with unique and such?! Dyalog sure is awesome. Also ,∘≢⌸ is shorter than {⍺,≢⍵}⌸. – user46915 – 2015-11-09T12:41:34.193

3@NBZ, I miss APL. Back in 1982 I wrote a graphics package in APL that drove a daisy wheel printer. It was a work of art, even though I didn't understand what I had written a month later. – vy32 – 2015-11-09T21:21:22.130

10

Mathematica, 48 bytes - 3 = 45

Grid@Tally@Flatten@IntegerDigits@Tuples@Range@#&

alephalpha

Posted 2015-11-08T12:40:54.690

Reputation: 23 988

1That's beautiful. – lirtosiast – 2015-11-08T22:20:53.387

2

R, 110 bytes

Saved 4 thanks to Alex A. (thanks!)

U=unlist
X=table(U(strsplit(as.character(U(expand.grid(Map(seq_len,scan())))),"")))
z=Map(cat,names(X),X,"\n")

flodel

Posted 2015-11-08T12:40:54.690

Reputation: 2 345

You only use x once so you should just be able to replace the one occurrence of x with scan(). Also why assign z? – Alex A. – 2015-11-08T23:36:41.620

Thanks. Agree about not using x. I assigned the output of Map to a z variable otherwise Map would print its output to stdout. A better practice would be to wrap Map inside invisible() but that's a lot of characters... – flodel – 2015-11-10T00:07:57.900

2

Mathematica, 111 85 bytes

Grid[Thread@{Range@10~Mod~10,DigitCount@Tuples@Range@#~Total~2}~DeleteCases~{_,‌​0}]&

Most of the work here is done by DigitCount.

LegionMammal978

Posted 2015-11-08T12:40:54.690

Reputation: 15 731

Grid[Thread@{Range@10~Mod~10,DigitCount@Tuples@Range@#~Total~2}~DeleteCases~{_,0}]& – alephalpha – 2015-11-08T15:45:11.253

1

Ruby, 92 bytes

f,*r=$*.map{|n|[*1..n.to_i]}
a=f.product(*r)*''
puts a.chars.uniq.map{|c|[c,a.count(c)]*" "}

Takes the lengths as command line arguments:

$ ruby foo.rb 1 2 3
1 11
2 5
3 2

daniero

Posted 2015-11-08T12:40:54.690

Reputation: 17 193

0

CJam, 31 bytes

Laq~{,m*}/e_:)s{_'0=A*+}$e`{(S\N}%

Try it online

Code is 34 bytes, and takes 3 byte bonus for working with empty input list. The input is a list in CJam format, e.g.:

[1 2 3]

Explanation:

La    Push list containing empty list to seed Cartesian products.
q~    Get and interpret input.
{     Loop over values in input list.
  ,     Built range from 0 to value-1.
  m*    Form Cartesian product with the list we already have.
}/    End loop over values in input list.
e_    Resulting list has extra nesting. Flatten it.
:)    Increment all values in list, since it is 0-based, and we need 1-based.
s     Convert it to string, so we can operate on digits.
{     Block to calculate source key, needed to get 0 to the end.
  _     Copy the digit.
  '0=   Compare with '0.
  A*    Multiply comparison result by 10...
  +     ... and add it to digit.
}$    End of sort key block.
e`    RLE.
{     Start of loop over RLE entries, for generating output in specified format.
  (     Pop off the first value, which is the count.
  S     Push a space...
  \     ... and swap it with the count.
  N     Push a newline.
}%    End of loop over RLE entries.

Reto Koradi

Posted 2015-11-08T12:40:54.690

Reputation: 4 870

0

Pyth, 15 bytes

rjko%N_Ts*FSMQ8

isaacg

Posted 2015-11-08T12:40:54.690

Reputation: 39 268

0

Haskell, 125 bytes

import Data.List
l=mapM_(putStrLn.(\(h:r)->h:' ':show(length r+1))).group.sort.concatMap show.concat.sequence.map(\n->[1..n])

Leif Willerts

Posted 2015-11-08T12:40:54.690

Reputation: 1 060