[Question]
  [
You may have seen something called a "perpetual dice calendar":  
[![perpetual dice calendar](https://i.stack.imgur.com/7O4xb.jpg)](https://i.stack.imgur.com/7O4xb.jpg)
Two 6-sided dice can be rearranged and rotated. One die has the numbers 0, 1, 2, 3, 4, and 5. The second die has the numbers 0, 1, 2, 6, 7, and 8. With this, any day of the month—from 1 to 31—can be displayed on the front of the calendar. *The `6` can be rotated to be used as a `9`.*
However, what if I wanted to display any number up to... 100? 365? 50287? How many 6-sided dice would I need then, and what numbers would be printed on their sides?
The challenge:
* Given a whole number input X, output the fewest possible 6-sided dice that are required to display all integers from 1 up to and including X.
* Each side of a die must contain exactly one integer, from 0 to 8 inclusive.
* `6`'s may be used as `9`'s.
* If not every side of every die needs to have a number on it, then those side(s) must have `0`.
* Each line of the output should represent a die, e.g.:
```
Input: 4
Output:
0 0 1 2 3 4
Input: 6
Output:
1 2 3 4 5 6
Input: 9
Output:
0 1 2 3 4 5
0 0 0 6 7 8
Input: 31
Output:
0 1 2 3 4 5
0 1 2 6 7 8
Input: 35
Output:
0 1 2 3 4 5
0 1 2 3 6 7
0 0 0 0 0 8
```
* The output lines can be in any format, e.g.:
```
123456
1 2 3 4 5 6
1,2,3,4,5,6
[1, 2, 3, 4, 5, 6]
```
* Assume that all the dice are used for every number, using leading 0's if necessary. For instance, if X is 35, then `2` would be displayed as `002`, because 3 dice are necessary.
* The outputted numbers do not need to be in any particular order.
* There may be multiple solutions for X. You need only output one.
* Standard golfing rules apply.
  
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~22~~ 20 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
D€EƇZḢḟ9s<7+5Ɗo0x6¤Y
```
A full program that accepts a positive integer and prints a set of dice as lines each having six digits from \$[0,8]\$.
**[Try it online!](https://tio.run/##y0rNyan8/9/lUdMa12PtUQ93LHq4Y75lsY25tumxrnyDCrNDSyL/6xxuV8l61DDHiutRw1xNEIsLxPr/38jICAA "Jelly – Try It Online")**
### How?
For small inputs (\$\le 6\$) we should fill a single die with the numbers we need and then zeros.
For larger numbers, we:
* need multiple dice since one dice only has six sides, and
* only place up to five non-zero digits on the first dice (since we will need at least one leading zero to represent small numbers like \$7\$ or \$8\$)
When we reach a rep-digit that is not repeated nines (e.g. \$444\$) we need to ensure that enough of the dice have that digit (in this case three of them), and that any others contain a zero (since we will need them in front to represent the rep-digit).
Thus an optimal output for numbers greater than six is to set the first face of every die to \$0\$ and fill the remaining faces with the digits \$1\$ to \$8\$ in order as required by either the number itself (excluding \$9\$) or the digit of the rep-digit we have reached that we cannot yet make.
Thus for inputs greater than six we:
* fill the first dice with \$[1,2,3,4,5,0]\$
* fill the second dice with \$[6,7,a,b,c,0]\$ where \$a\$, \$b\$ and \$c\$ are \$0\$ until we encounter \$8\$ (a non-nines rep-digit), \$11\$ and \$22\$ whereupon they should be filled with \$8\$, \$1\$ and \$2\$ respectively.
* at \$33\$ create a new dice \$[3,d,e,f,g,0]\$ where \$d\$, \$e\$, \$f\$, and \$g\$ are \$0\$ until we encounter \$44\$, \$55\$, \$66\$, and \$77\$ whereupon they should be filled with \$4\$, \$5\$, \$6\$, and \$7\$ respectively.
* etc.
```
D€EƇZḢḟ9s<7+5Ɗo0x6¤Y - Main Link: positive integer, N
 €                   - for each i in [1,N]:
D                    -   decimal digits
   Ƈ                 - keep those for which:
  E                  -   all equal -> [[1],[2],...,[9],[1,1],[2,2],...,[9,9],...,[1,1,1],...]
    Z                - transpose
     Ḣ               - head -> [1,2,...,9,1,2,...,9,1,...]
      ḟ9             - filter out nines
             Ɗ       - last three links as a monad - f(N):
         <7          -   less than seven?
            5        -   five
           +         -   add -> 6 if N < 7 else 5
        s            - (filtered list of digits) split into chunks of length (that)
                          e.g.:  N=3 -> [[1,2,3]]
                                N=44 -> [[1,2,3,4,5],[6,7,8,1,2],[3,4]]
                  ¤  - nilad followed by link(s) as a nilad:
               0     -   zero
                 6   -   six
                x    -   repeat -> [0,0,0,0,0,0]
              o      - logical OR (vectorises)
                          e.g.:  N=3 -> [[1,2,3,0,0,0]]
                                N=44 -> [[1,2,3,4,5,0],[6,7,8,1,2,0],[3,4,0,0,0,0]]
                   Y - join with newline characters
```
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal), ~~29~~ 17 bytes
```
~≈∩h9F5?6=+ẇṅ6∆Z⁋
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyIiLCIiLCJ+4omI4oipaDlGNT82PSvhuofhuYU24oiGWuKBiyIsIiIsIjU1NSJd)
*-12 bytes by taking some ideas from @Jonathan Allan's Jelly answer*
I believe this is correct but I'm not completely sure.
```
~≈                # keep only those numbers where all digits are equal from the implicit range [1, input]
  ∩               # transpose
   h              # first element
    9F            # remove nines 
      5?6=+       # 6 if input is 6 otherwise 5
           ẇ      # split into chunks of that length
            ṅ     # join
             6∆Z  # pad with zeros to length 6
                ⁋ # join by newlines
```
[Answer]
# Python3, 475 bytes:
```
from itertools import*
R=range
N=lambda k:k+[6,9]*(6 in k or 9 in k)
P=permutations
def f(n):
 q=[({*R(1,n+1)},[[]]if n<7 else[[0]])]
 while q:
  a,b=q.pop()
  if not a:return[[0]*(6-len(i))+i for i in b]
  t=str(min(a))
  for i in P(b,min(len(b),len(t))):
   for j,k in zip_longest(t,i):
    j=int(j)
    if not k or j not in N(k):
     D=[*b,[0,j]]if len(b[-1])==6 else[*b[:-1],b[-1]+[j]];q+=[(a-{int(''.join(map(str,K)))for d in P(D,len(D))for K in product(*map(N,d))},D)]
```
[Try it online!](https://tio.run/##PVDLbsMgEDzXX7G3gE2iRGndxi233CJFUa4IVbjGDX4AwURVG/XbU7CrHBDs7Aw7s/bbn4xev1h3u9XO9KC8dN6YbgDVW@N8mhypE/pTJnvaib6sBLRFm7GcbHiKclAaWjAONuMLJwdqpesvXnhl9JBUsoYaaVwkcKYMXdMjWhGdrfAvYYxzVYN@ewbZDZKxJeeYJ/B1Up2Ec1CAICU9L6yxCIcqko0HUTjpL05HQXAw76RGCuNMQR18qOijDN@Ap4N3qFcaCRzl9@4BlSTCUVhiEi@PcbQ4kRrSRtqPsu@dCckHjzxRUx8aqrRHDR6Lf0fjAprxGXR71P5zYUtZWhK2JM0YdRzI5iuOKc2n0GnJigCQEc5Y4L2es7AoMb/GObPZojHBai8sCmnILviMFqspx3Y0v52wXcSsM9Xlw6M0KvakwmHRW8xv9/DskUBOYENgvQrniRfJg3VxVh23ePsD)
[Answer]
# Excel, ~~161 122 120~~ 122 bytes
*saved 39 bytes after looking at AndrovT's solution and fixing error for n=6*
*saved 2 more bytes after realizing the die for N=6 didn't need to have a 1*
*added 2 bytes because the previous statement was false*
```
=LET(x,ROW(1:8),y,LEN(A1),z,A1=6,IFERROR(HSTACK(z*1,MOD(SEQUENCE(INT((y*8+MAX(x*(REPT(x,y)*1<=A1))-4-z)/5),5)+z-1,8)+1),))
```
The formula above determines how many faces are needed to cover all numbers less than or equal to N then generates dice from the list below so there at least that many faces.
```
0 1 2 3 4 5
0 6 7 8 1 2
0 3 4 5 6 7
0 8 1 2 3 4
0 5 6 7 8 1
0 2 3 4 5 6
0 7 8 1 2 3
0 4 5 6 7 8 
```
If N = 6 it uses `1 2 3 4 5 6`.
**Explanation:**
```
=LET(x,ROW(1:8),           # x = array 1..8
y,LEN(A1),                 # y = number of digits in N 
z,A1=6,                    # z = (N=6)
IFERROR(~,)                # Pads errors with 0
HSTACK(z*1,~)                # Concatenates 0 to other 5 faces
MOD(SEQUENCE(~,5)+z-1,8)+1 # array of last 5 faces for each die
INT((~)/5)                 # number of dice needed
y*8+MAX(x*(~))-4-z         # 4 + number of faces needed to cover all numbers up to ~
REPT(x,y)*1<=A1            # calculates the largest number the same length as N with repeated digits
                           
```
[Answer]
# JavaScript (ES8), 111 bytes
Algorithm shamelessly borrowed from [@AndrovT](https://codegolf.stackexchange.com/a/260444/58563)'s latest version, which itself uses ideas from [@JonathanAllan](https://codegolf.stackexchange.com/a/260448/58563).
Returns an array of digit strings.
```
n=>n-6?(g=n=>n?g(n-1)+(/^([1-8])\1*$/.test(n)?n%10:''):'')(n).match(/.{1,5}/g).map(s=>s.padEnd(6,0)):["123456"]
```
[Try it online!](https://tio.run/##HYzLCsIwFET3fkUQxRtNU6O2@CDtyo0LXbisFUIfsaI3pQmCiN9eWwcOzJnF3NVL2aypauehyYu2lC3KCL0wBi37FmtAT9AZ@FdIhLdO6UVMRz53hXWANMaxmG8nE9rTOX8ql93A5x/Bgq@v@6EGKyPLa5XvMYeQzSndJkOxWK6CcJi2u2TFSMjIhpGl6AjSAS9Ns1fdDxIZkcygNY@CP4yGw/l05NY1FeqqfEMJyJ05/x1on/YH "JavaScript (Node.js) – Try It Online")
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 29 bytes
```
Ｅ⪪⁻⭆ΦＩ…·¹Ｎ⁼⌊ι⌈ι⌊ι9⁺⁵⁼θ6⭆◨ι⁶Σλ
```
[Try it online!](https://tio.run/##RYxBCsIwEEWvUrKaQgVdWCoui0IXlWK9QAyhHUjStEmKnj5Oiuhm@PPmzRcjX8TEVYzdgsZDyy30ViElNMFB7wkPiV5ReblAzZ2HxggVHK7yzs0g4VBkjbHB34J@kpLneZFd5sCVSy2ogwYk1PLXNyfhf6GFnRjNjkrh@PudiZdsk@u3ULIeJwubg0X2QC03me1ZMkryzjFWVdyt6gM "Charcoal – Try It Online") Link is to verbose version of code. Explanation: Once I'd figured out what the problem actually was, this is an implementation of @Axuary's observation, although comparing the other answers I see I ended up with the same basic algorithm as @AndrovT and @JonathanAllan but only by coincidence.
```
      …·                        Inclusive range from
        ¹                       Literal integer `1` to
         Ｎ                      First input as a number
     Ｉ                          Vectorised cast to string
    Φ                           Filtered where
           ⌊ι                   Minimum digit
          ⁼                     Is equal to
             ⌈ι                 Maximum digit
   ⭆           ⌊ι               Extract one digit from each repdigit
  ⁻              9              Remove `9`s
 ⪪                              Split into groups of
                   ⁵            Literal integer `5`
                  ⁺             Plus
                     θ          First input
                    ⁼           Equals
                      6         Literal string `6`
Ｅ                              Map over groups
                        ◨ι⁶     Pad to 6 characters
                       ⭆   Σλ   Replace spaces with `0`s
                                Implicitly print
```
The above code is sublinear in `X`, so here's more efficient 35-byte version:
```
Ｅ⪪⁻⭆⁺÷×⁹⊕ＮＸχＬθ×⁹⊖Ｌθ﹪⊕ι⁹0⁺⁵⁼θ6⭆◨ι⁶Σλ
```
[Try it online!](https://tio.run/##TY7NDoIwEIRfpeG0JDXBgwTiFQ8kYoj4AhUa2KQ/UFp8/NpyUG673@zMTj8x02smvG8NKgsNm6GbBYYJlVuhswGPkbYirLWyFW44cHih5CuUlNSqN1xyZfkQ5NnZh5NvbiBNU0pa/QnjOaPkztVoJ1h2/DNX/G8@XISTRg9OaDimY8Bl1JIsidmx0IWS2@KYWGEJPE9276E0G544ThaQkjwqToKID67eF4U/beIL "Charcoal – Try It Online") Link is to verbose version of code. Explanation: Calculates the number of repdigits up to `X` as equal to the first digit of `(X+1)*9` plus `9` times the length of `X` as a string plus a correction factor, then takes the sequence modulo `9` omitting the zeros and wraps into rows as above.
The problem would have been much more interesting if each number only needed to be formed from `1+floor(log10(X))` dice. In that case, my best patterns so far are as follows:
* 6: 123456
* 9: 123456, 78
* 10: 012345, 0678
* 21: 012345, 06781
* 32: 123450, 678012
* 54: 123456, 781234, 0
* 65: 123456, 781234, 05
* 76: 123456, 781234, 056
* 87: 123456, 781234, 0567
* 99: 123456, 781234, 05678
* 221: 123456, 781234, 056781, 0
* 332: 123456, 781234, 056781, 02
* 443: 123456, 781234, 056781, 023
* 554: 123456, 781234, 056781, 0234
* 665: 123456, 781234, 056781, 02345
* 776: 123456, 781234, 056781, 023456
* 887: 123456, 781234, 056781, 023456, 7
* 999: 123456, 781234, 056781, 023456, 78
* 1110: 123456, 781234, 056781, 023456, 780
* 2221: 123456, 781234, 056781, 023456, 7801
* 3332: 123456, 781234, 056781, 023456, 78012
* 4443: 123456, 781234, 056781, 023456, 780123
I believe that the dice will then continue cyclically though the digits after that point.
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), 44 (or 42†) [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
[8Ý6ãNã.ΔULε§Xgj„9 60‡œεXsøε`å}P}à}P}D¸àd#}»
```
Extremely slow brute-force, so it'll time out for \$n\geq7\$ on TIO..  
Not too happy with how long `§Igj„9 60‡œεXsøε`å}P}à` is. Will see if I can find something shorter (and hopefully faster) later on.
[Try it online](https://tio.run/##AUoAtf9vc2FiaWX//1s4w502w6NOw6MuzpRVTM61wqdYZ2rigJ45IDYw4oChxZPOtVhzw7jOtWDDpX1QfcOgfVB9RMK4w6BkI33Cu///NA) or [verify some of the smaller test cases](https://tio.run/##yy9OTMpM/W96bJKSZ15BaYmVgpK936GVOlxK/qUlEL7O/2iLw3PNDi/2O7xY79yU0EPrDs89t/XQ8oj0rEcN8ywVzAweNSw8Ovnc1ojiwzvObU04vLQ2oPbwAiDhcmjH4QUpyrWHdv/XObTN/j8A).
† With looser output-format of a list of lists of digits, the trailing `}»` can be removed for -2 bytes.
**Explanation:**
```
[               # Start an infinite loop:
 8Ý             #  Push a list in the range [0,8]
   6ã           #  Cartesian power of 6 to create all sextets using these digits
     Nã         #  Cartesian power with the 0-based loop-index
 .Δ             #  Find the first one that's truthy for,
                #  or -1 if none are truthy:
   U            #   Pop and store the current list in variable `X`
   Ý            #   Push a list in the range [0, (implicit) input-integer]
    ε           #   Map over each value:
      Xg        #    Push the length of list `X`
     §  j       #    Pad leading spaces to make the current integer that length
         „9 60‡ #    Transliterate 9s to 6s and spaces to 0s
     œ          #    Get all permutations of this integer
      ε         #    Map over each permutation:
       Xs       #     Push list of lists `X` and swap
         ø      #     Create pairs of the two lists
          ε     #     Map over each pair of [list,digit]
           `    #      Pop and push the list and digit separately to the stack
            å   #      Check if the digit is in the list
          }P    #     After the map: check whether it's truthy for all [list,digit]-pairs
      }à        #    After the map: check whether it's truthy for any permutation
    }P          #   After the map: check whether it's truthy for all values in the range
  }D            #  After the find_first: Duplicate the resulting -1 or list
    ¸           #  Wrap it into a list
     à          #  Pop and push the flattened maximum
      d         #  If this maximum is non-negative (thus not -1):
       #        #   Stop the infinite loop
}»              # After the infinite loop: join each inner list of the valid find_first
                # by spaces, and then all strings by newlines
                # (after which it is output implicitly as result)
```
[Answer]
# [Nibbles](http://golfscript.com/nibbles/index.html), 18 bytes (36 nibbles)
```
&"0"6`/ ?-$6 5 $ |+|.,$`$`@~$~<<$- 9
```
Same approach as [Androv T's answer](https://codegolf.stackexchange.com/a/260444/95126): upvote that one!
```
|+|.,$`$`@~$~<<$- 9 # part 1: get the nonzero digits needed:
   .                # map over
    ,               # range from 1..
     $              # input
        `@ $        #   convert to digits in base           
          ~         #   10
      `$            #   and remove duplicates
  |                 # now filter to keep only
            ~       # falsy elements when
             <<$    #   dropping the first element of each list
 +                  # flatten the list of (1-element) lists
|                   # and filter again to keep only
                    # elements that are truthy (positive) when
                - 9 #   subtracted from 9
&"0"6`/ ?-$6 5 $    # part 2: split them into dice:
     `/             # split into chunks of
        ?           #   if
         -$6        #     input minus 6 is truthy
             5      #   then 5
               $    #   else input
&                   # now justify each chunk
    6               # to a width of 6
 "0"                # using "0" as a filler
```
[![enter image description here](https://i.stack.imgur.com/aDhaM.png)](https://i.stack.imgur.com/aDhaM.png)
---
Frustratingly, if we were allowed to use `9`s instead of `6`s (rather than `6`s instead of `9`s), which would correspond to identical physical dice, we could have:
# [Nibbles](http://golfscript.com/nibbles/index.html), 16.5 bytes (33 nibbles; but not permitted output)
```
&"0";6`/ +`$- $@ $ +`%+|.,@`$`@~$~<<
```
[![enter image description here](https://i.stack.imgur.com/Cw1g7.png)](https://i.stack.imgur.com/Cw1g7.png)
[Answer]
# [Python 2](https://docs.python.org/2/), 120 bytes
```
n=input()
m=n>6
for v in zip(*[(i%10for i in range(n>1,n+1)+4*[0]if len(set(`i`))<2-i%10/9)]*(6-m)):print'0'*m+`v`[1::3]
```
A full program that accepts a positive integer from STDIN and prints the dice.
**[Try it online!](https://tio.run/##FcvRCoIwFADQd79iL@G9W5KzEBvpj4zBetC60K5jLaF@fuHrgRO/@blyVwqPxPGTAasw8tRXy5rEJojFjyJIC3TQ7W60W7rzYwae9JGVRnWRtnW0iNfM8J4zePKIt67Zz@mKTkLfBEQTE3Gu21oG5TdvtTFnV8ow/AE "Python 2 – Try It Online")** Or see the [test-suite](https://tio.run/##RVDRasMwDHz3V@hl2E6cLU7arDVzfyQLJG3dzlArIfXK1rJvz2wzmEDoOKS7Q9O3/xixWg7j0WhK6fuC2uL06RknTuOuIadxhhtYhLudWNYy@yTLyNnIzQOeDcOdFJhLnq@ytuzsCS4G2dV41tue87eqiDcvW95lrCkc52qaLXpa0szl/a1vpVJ1twT3VhWyIyQF0JfB7Y@D8ubqU4gIoieTAioBtYCVgEbANuBA1WsBm9fQGwEyVvk3JVcEQiVToEkcNDx@FH0Oum7wLErztGS@zAHiM/5Pll8 "Python 2 – Try It Online").
This employs the same method I used in [my Jelly answer](https://codegolf.stackexchange.com/a/260448/53748).
]