# Background

The monkeys need help organizing their defense and have asked you, Benjamin the code monkey, to create a program that will list all tower upgrade options. Each tower has three unique upgrade "paths", each having a tier represented by a number between 0 and 5 inclusive, 0 meaning no upgrade. Up to two paths may be chosen for upgrading, that is contain an upgrade tier 1 or greater. Additionally, only one path can can contain a tier 3 or greater.

Output in some reasonable format all valid upgrade path triples in any order (the triples themselves are ordered). Triples can be represented in any reasonable way, such as 025 or 0-2-5. The triples must be distinguishable from each other in some way, so a flat list of numbers without triple delimiters is not allowed.

Here is an example list of all 64 possible triples, as they appear in-game for your insta-monkey collection:

5-2-0
5-0-2
5-1-0
5-0-1
5-0-0
2-5-0
0-5-2
1-5-0
0-5-1
0-5-0
2-0-5
0-2-5
1-0-5
0-1-5
0-0-5
4-2-0
4-0-2
4-1-0
4-0-1
4-0-0
2-4-0
0-4-2
1-4-0
0-4-1
0-4-0
2-0-4
0-2-4
1-0-4
0-1-4
0-0-4
3-2-0
3-0-2
3-1-0
3-0-1
3-0-0
2-3-0
0-3-2
1-3-0
0-3-1
0-3-0
2-0-3
0-2-3
1-0-3
0-1-3
0-0-3
2-2-0
2-0-2
2-1-0
2-0-1
2-0-0
0-2-2
1-2-0
0-2-1
0-2-0
1-0-2
0-1-2
0-0-2
1-1-0
1-0-1
1-0-0
0-1-1
0-1-0
0-0-1
0-0-0

• Are we allowed to output duplicates? (assuming no) Jun 30 at 23:06
• @thejonymyster no, there should be exactly 64 triples
– qwr
Jun 30 at 23:21

# K (ngn/k), 20 18 bytes

?,/+'!'1|3*<'+!3#3


Try it online!

+!3#3 All triples with values in 0 1 2.
<' Grade up each triple. This results in all permutations of 0 1 2 with some duplicates.
1|3* Multiply by 3 and take maximum with 1 to generate all permutations of 6 3 1.
+'!' For each permutation, generate all triples where the each entry is a non-negative integer less than the number in the permutation at the same index.
?,/ Flatten into a matrix with three columns and take the unique rows.

# Factor + math.combinatorics, 59 58 bytes

6 iota 3 selections [ natural-sort "\0"before? ] filter .


Try it online!

-1 byte from a tip by @ovs.

Note the string "\0" has literal control character 3 embedded as well as the 0; you can see it on TIO. This string is equivalent to the longer (but clearer) sequence { 0 3 }.

• 6 iota 3 selections

Generate all 3-selections of $$\[0..5]\$$: { { 0 0 0 } { 0 0 1 } ... { 5 5 5 } }

• [ natural-sort { 0 3 } before? ] filter

Select those that when sorted are less than { 0 3 }.

• .

Print them.

# Python 2, 82 80 bytes

from itertools import*
print[k for k in product(*[range(6)]*3)if[0,3]>sorted(k)]


-2 bytes thanks to @ovs.

Try it online.

Explanation:

• from itertools import*: Import itertools for the cartesian product builtin
• range(6): Push list [0,1,2,3,4,5]
• [^]*3: Repeat it three times: [[0,1,2,3,4,5],[0,1,2,3,4,5],[0,1,2,3,4,5]]
• product(*^): Use the cartesian product builtin to get all triplets
• k for k in ^: Loop over these triplets
• ^if: And filter to only keep the triple-tuplets k that are:
• sorted(k): When sorted and converted to an array
• [0,3]>^: are smaller than [0,3]
• [^]: Wrap all these tuplets into an array
• print^: And print it as result
• I think [0,3]>sorted(k) is sufficient
– ovs
Jun 30 at 21:06
• @ovs Thanks! :) Jul 1 at 6:24
• Surely [range(6] is roughly equivalent to [[0,1,2,3,4,5]], so that [range[6]]*3 is [[0,1,2,3,4,5],[0,1,2,3,4,5],[0,1,2,3,4,5]]?
– Neil
Jul 2 at 9:42
• @Neil You're right. I've changed the explanation accordingly. Jul 2 at 11:17

# Python, 71 bytes

for x in range(521):max(s:='%03d'%x)<'6'!=['0','3']>sorted(s)==print(s)

Attempt This Online!

I took the ['0','3']>sorted(s) idea from ovs.

# Husk, 10 bytes

uΣmPΠmŀ∫ḣ3


Try it online!

       ∫ḣ3  -- cumulative sums of [1..3] -> [1,3,6]
mŀ     -- lowered range of each     -> [[0],[0,1,2],[0,1,2,3,4,5]]
Π       -- cartesian product of the three lists
mP        -- for each triplet, get all permutations
Σ          -- flatten into a list of triplets
u           -- get the unique ones


# JavaScript (V8),  75  67 bytes

Saved 8 bytes thanks to @tsh

Prints one comma-separated triplet per line.

for(i=216;i--;)[...a=[i/36%6|0,i/6%6|0,i%6]].sort()<'0,3'&&print(a)


Try it online!

• Maybe for(i=216;i--;)[...a=[i/36%6|0,i/6%6|0,i%6]].sort()<'0,3'&&print(a)?
– tsh
Jul 1 at 3:31

# 05AB1E, 13 11 bytes

5Ý3ãʒ{₆1š‹P


-2 bytes thanks to a tip of @ovs using 136.

Outputs as a list of triplets.

Try it online.

Explanation:

5Ý           # Push a list in the range [0,5]
3ã         # Cartesian power of 3: get all triplets using these [0,1,2,3,4,5]
ʒ        # Filter this list by:
{       #  Sort the triplet from lowest to highest
ƵZ     #  Push compressed integer 136
S    #  Convert it to a list of digits: [1,3,6]
‹   #  Check for sorted triplet [a,b,c] whether [a<1,b<3,c<6]
P  #  Check if all three are truthy
# (after which the filtered list of 64 triplets is output implicitly)


ƵZS could alternatively be ₆1š for the same byte-count: try it online.

      ₆      #  Push 36
1š    #  Convert it to a list of digits, and prepend 1


See this 05AB1E tip of mine (section How to compress large integers?) to understand why ƵZ is 136.

• There is a 11-byter that uses a single filter. ƵZ might be a hint ;)
– ovs
Jun 30 at 18:19
• @ovs Smart! Thanks for the hint. :) Jun 30 at 18:30

# Retina 0.8.2, 50 bytes


520$*¶ 00$.
.+(...)
$1 G0 A[3-5].*[3-5]|[6-9]  Try it online! Link includes footer that prettifies the output. Explanation:  520$*¶

00$. .+(...)$1


List all the integers from 0 to 520 inclusive, padded to 3 digits.

G0


Only keep those integers with at least one 0 digit.

A[3-5].*[3-5]|[6-9]


Discard those with more than one digit greater than 2 or with a digit greater than 5.

• I was looking forward to a regex solution!
– qwr
Jul 1 at 16:28

# Python 3, 75 bytes

print([r for r in[(x//36,x//6%6,x%6)for x in range(216)]if[0,3]>sorted(r)])


Try it online!

# Charcoal, 26 bytes

ΦＥφ﹪%03dι∧№ι0∧›6⌈ι›²ΣＥι‹2λ


Try it online! Link is to verbose version of code. Explanation:

  φ                         Predefined variable 1000
Ｅ                          Map over implicit range
ι                   Current value
﹪%03d                    Formatted to 3 0-filled digits
Φ                           Filtered where
ι                Current value
№                 Contains
0               Literal string 0
∧                  Logical And
6            Literal string 6
›             Is greater than
ι          Current value
⌈           Maximum character
∧              Logical And
²        Literal integer 2
›         Is greater than
ι     Current value
Ｅ      Map over digits
2   Literal string 2
‹    Is less than
λ  Current digit
Σ       Take the sum
Implicitly print


28 bytes for the prettier version:

ΦＥφ⪫﹪%03dι-∧№ι0∧›6⌈ι›²ΣＥι‹2λ


Try it online! Link is to verbose version of code.

# Python 3, 161146 141 bytes

from itertools import*
for u in product(*[range(6)]*3):
i,j,k=u
if 0not in[i,j,k]or i>2and j>2or j>2and k>2or k>2and i>2:continue
print(u)


Try it online!

-5 thanks to qwr

• You can probably use itertools cartesian product and filter lambda to save some bytes over triple for loop
– qwr
Jun 30 at 20:55
• @qwr I don't know what is itertools, Can you upload a TIO link? Jun 30 at 21:02
• See Kevin Cruijssen's answer for an example
– qwr
Jun 30 at 21:04
• @qwr Thanks, -5 bytes. Jul 1 at 0:14

# Ruby, 62 bytes

p (z=*0..5).product(z,z).select{|x|x.min<1&&(x-[3,4,5])[1]}|[]


Try it online!

# Rust, 106 bytes

for i in 0..6{for j in 0..6{for k in 0..6{let mut t=[i,j,k];t.sort();if t<[0,3,6]{print!("{i}{j}{k}
")}}}}


Actually using nested loops is barely shorter than my attempt using itertoools.

Attempt This Online!

# Pyth, 12 bytes

f>,Z3ST^U6 3


Try it online!

Port of Kevin Cruijssen's Python answer

f>,Z3ST^U6 3
U6    Range up to 6 = [0,1,2,3,4,5]
^   3  Cartesian product with itself 3 times = [0,1,2,3,4,5] * [0,1,2,3,4,5] * [0,1,2,3,4,5]
f             Filter for elements T such that:
>,Z3ST       [0,3] > sorted(T)


# Regenerate-a, 73 64 bytes

[345]([12]0|0[012])|[12]([1-5]0|0[0-5])|0([012][0-5]|[345][012])

Attempt This Online!

Surprised nopony did this yet. Probably golfable!

EDIT: -9 thanks to math junkie for reminding me of the shorter output format. Now it's 1 byte per combination :P I still think it can be golfed further, possibly with a new approach :-)c

• I think you can drop the - separators since that's allowed by the challenge rules Jul 11 at 1:23
• @mathjunkie omg i forgot thank u Jul 11 at 2:40

# Batch, 271 bytes

@!! 2>nul||cmd/q/v/c%0&&exit/b&for /l %%i in (0,1,5)do @(for /l %%j in (0,1,5)do @(for /l %%k in (0,1,5)do @(set s=%%i%%j%%k&set p=!s:0=!&if !p:~!==~ set p=0
if !p!. neq !s!. set/af=!p!/10&set/al=!p!%%10&if !f! lss !l! (if !f! leq 2 echo !s!)else if !l! leq 2 echo !s!)))