# CSI: Minecraft Items

Minecraft 1.12 will be released tomorrow, so let's celebrate!

Write code that takes in a non-negative integer N which represents the number of items of something in Minecraft. Output it in a way more helpful to players, giving the number of chests, stacks, and items N is equivalent to. Use the format

XcYsZi


where

• X is the number of chests you can completely fill with N items,
• Y is the number of stacks you can fill with the items remaining after filling chests,
• Z if the number of items remaining after filling chests and stacks.

Note that:

• 64 items fit in a stack. (We'll ignore items that stack to 16 or don't stack.)
• 27 stacks fit in a chest. (These are single chests, not double chests.)

So it would never make sense if Y is more than 26 or if Z is more than 63.

A caveat with the format is that if there is zero of something, that term is not printed.

• So, for example, if Y were zero and X and Z nonzero, the format would look like XcZi.

• Likewise if Y and Z were zero and X nonzero, the format would be Xc.

• The exception here is when N is zero. Then 0i is the output rather than an empty string.

You can assume all N items are of the same type, hence all stackable.

You may not output a list or tuple of three numbers. You must give a string with the exact "csi" notation, in that order, with no spaces or commas.

For reference, here's a chest completely filled with stacks of items:

# Testcases

in -> out
0 -> 0i
1 -> 1i
2 -> 2i
62 -> 62i
63 -> 63i
64 -> 1s
65 -> 1s1i
66 -> 1s2i
127 -> 1s63i
128 -> 2s
129 -> 2s1i
200 -> 3s8i
512 -> 8s
1337 -> 20s57i
1664 -> 26s
1727 -> 26s63i
1728 -> 1c
1729 -> 1c1i
1791 -> 1c63i
1792 -> 1c1s
1793 -> 1c1s1i
4096 -> 2c10s
5183 -> 2c26s63i
5184 -> 3c
5200 -> 3c16i
9999 -> 5c21s15i
385026 -> 222c22s2i
1000000000 -> 578703c19s


The shortest code in bytes wins.

• Related Jun 7 '17 at 6:18
• ok apparently this is a crime scene investigation
– Okx
Jun 7 '17 at 6:30
• Related. Jun 7 '17 at 6:39
• @Okx with all the spinoffs that wouldn't be surprising. Now we need a challenge with drawing a chalk outline -- of a creeper perhaps Jun 8 '17 at 9:01
• Mulling it over now, but I don't think this challenge can be done in Minecraft. No way to concatenate the output string. Maybe I could display the result as an actual pile of chests, blocks, and items :) Jun 8 '17 at 21:06

# Jelly,  26  24 bytes

d64d1¦27Fża¥“csi”Fḟ0ȯ⁾0i


A full program taking the number and printing the result.
It does seem too long to me...

Try it online! or see the test suite.

### How?

updating...

d64d1¦27Fża¥“csi”Fḟ0ȯ⁾0i - Main link: number n
64                      - literal 64
d                        - divmod (whole divisions and remainder)
27                 - literal 27
1¦                   - apply to index 1 (the whole division from above)
d                     - divmod
F                - flatten into a single list (of three items i.e. [(n/64)/27, (n/64)%27, n%64]
“csi”        - literal ['c','s','i']
ż               -   zip
a              -   logical and (any 0s in the divmod result become [0,0], others become [integer, character]
F       - flatten (from list of three lists to one list)
⁾0i - literal ['0','i']
ȯ    - logical or (non-vectorising)
- implicit print (smashed together representation, so [578703,'c',19,'i'] prints as 578703c19i)


# Retina, 4948 41 bytes

.+
$*i i{64} s s{27} c (.)\1*$.&$1 ^$
0i


Try it online! Includes all test cases except the last, in case it overloaded TIO. Edit: Saved 7 bytes thanks to @MartinEnder. Explanation:

.+
$*i  Convert the input number to unary using is. i{64} s  64 items fill one stack. s{27} c  27 stacks fill one chest. (.)\1*$.&$1  Convert any chests, stacks or remaining items to decimal, but leaving the type as a suffix. ^$
0i


If the input was zero, make the result 0i.

• Oh my is this really converting to unary then replacing? Jun 7 '17 at 8:03
• @JonathanAllan I've added an explanation (I didn't have time earlier sorry). (Writing the explanation gave me an opportunity to save a byte too!)
– Neil
Jun 7 '17 at 8:43
• You can avoid some of that $.& duplication like this: tio.run/##FYs9DsIwDIX3d46ASpGq2Ens5ARcAiEQYsjCQNmqnj21Lb9veD@/… Jun 7 '17 at 9:43 • @MartinEnder Ah, I was wondering whether it would be worthwhile converting directly to i instead of 1, but I just couldn't see that simplification, thanks! – Neil Jun 7 '17 at 11:52 # 05AB1E, 24 bytes 1728‰64‰)˜…csiøvyJ¬0Êi?  Try it online! Explanation 1728‰ # input divmod 1728 (64*27)  # split as separate with mod result on top of stack 64‰ # divmod 64 )˜ # wrap stack in flattened list …csiø # zip with the string "csi" vy # for each J # join amount with storage-type ¬0Êi # if head != 0 ? # print  • How does it work in the 0 input case, and why does that also print a trailing newline while other inputs don't? Jun 7 '17 at 8:32 • @JonathanAllan: If nothing has been printed, 05AB1E implicitly prints the top of the stack at the end of execution (with newline). For-loops breaks lists apart and pushes the elements to the stack, so any item not printed will be added to the stack. At the end of the loop in the 0 case 0i will be on the top of the stack (0s and 0c will be under it) and will be printed. Jun 7 '17 at 8:36 • 1728 can be Ž6Ç now; and 0Ê can be Ā. Feb 12 at 8:22 # C#, 84 86 bytes _=>(_/1728>0?_/1728+"c":"")+((_-=_/1728*1728)/64>0?_/64+"s":"")+(_%64>0?_%64+"i":"")  Notice the inline subtraction, didn't realize it was possible but i-- made sense so why not i-=10 # Edit: _=>_>0?(_/1728>0?_/1728+"c":"")+((_%=1728)/64>0?_/64+"s":"")+(_%64>0?_%64+"i":""):"0i"  for 0 edge case and suggestion. • +1. And you can change _-=_/1728*1728 to _%=1728 to golf a few bytes. Jun 7 '17 at 10:48 • Also, you forgot about the edge case 0, which should result in 0i and is currently outputting nothing. Adding a simply _>0?...:"0i" would fix this. Jun 7 '17 at 10:55 • @KevinCruijssen Ahh, thank you. Jun 7 '17 at 10:56 • +1 for >_> in the edited one Jun 7 '17 at 15:16 # Python 3, 87 bytes lambda n:g(n//1728,"c")+g(n//64%27,"s")+g(n%64,"i")or"0i" g=lambda n,s:(str(n)+s)*(n>0)  Try it online! • In Python 2 this could be shortened to 82 bytes, using simple division (/ instead of //) and using backtick operator instead of str(...) Jun 7 '17 at 9:35 # C, 85 87105110111112 bytes #define a(x,y)x?printf("%d%c",x,y+99):0; f(z){a(z/1728,0)a(z%1728/64,16)!z+a(z%64,6)}  Try it here. The code even works properly on negative numbers. You may now owe server OP blocks! • Functions are acceptable as standard on PPCG Jun 7 '17 at 11:27 • 83 bytes Jul 10 '20 at 16:37 ## JavaScript (ES6), 77 76 bytes n=>[n+1,1728,64,1].map((v,i,a)=>(v=n%a[--i]/v|0)?v+'csi'[i]:'').join||'0i'  ### Test cases let f = n=>[n+1,1728,64,1].map((v,i,a)=>(v=n%a[--i]/v|0)?v+'csi'[i]:'').join||'0i' console.log(f(0)) // -> 0i console.log(f(1)) // -> 1i console.log(f(2)) // -> 2i console.log(f(62)) // -> 62i console.log(f(63)) // -> 63i console.log(f(64)) // -> 1s console.log(f(65)) // -> 1s1i console.log(f(66)) // -> 1s2i console.log(f(127)) // -> 1s63i console.log(f(128)) // -> 2s console.log(f(129)) // -> 2s1i console.log(f(200)) // -> 3s8i console.log(f(512)) // -> 8s console.log(f(1337)) // -> 20s57i console.log(f(1664)) // -> 26s console.log(f(1727)) // -> 26s63i console.log(f(1728)) // -> 1c console.log(f(1729)) // -> 1c1i console.log(f(1791)) // -> 1c63i console.log(f(1792)) // -> 1c1s console.log(f(1793)) // -> 1c1s1i console.log(f(4096)) // -> 2c10s console.log(f(5183)) // -> 2c26s63i console.log(f(5184)) // -> 3c console.log(f(5200)) // -> 3c16i console.log(f(9999)) // -> 5c21s15i console.log(f(385026)) // -> 222c22s2i console.log(f(1000000000)) // -> 578703c19s # Java 8, 86 bytes i->i>0?(i/1728>0?i/1728+"c":"")+((i%=1728)/64>0?i/64+"s":"")+((i%=64)>0?i+"i":""):"0i"  Try it here. # CJam, 31 bytes ri64md\27md@]"csi"]z{0=},"0i"e|  Try it online! ### Explanation ri e# Read an int from input. 64md e# Divmod by 64, gives total #stacks, #items. \27md e# Divmod total #stacks by 27, gives #chests, #stacks. @ e# Bring #items back to top. ] e# Wrap in an array: [#chests, #stacks, #items] "csi" e# Push "csi". ]z e# Zip with the other array. {0=}, e# Filter out subarrays where the first element is 0. "0i"e| e# Logical or with "0i". An input of 0 gives an empty array e# from the rest of the program, in that case yield "0i" e# instead.  # ///, 179 bytes /|/\/\///b/l0|d/11|x/dddd|sbxxxxxxxx/1sb|cbxxxd1/1cb|bxd/1b|d/2|2222/8|222/6|22/4|21/3|81/9|61/7|41/5|bc/gc|cb/c|bs/gs|sb/s|bi/gi|b|/g/0|mc/m|ms/m|mi/0i|m|/si/s|cs/c|ci/c/mcl0sl0i  Try it online! Input is taken in unary 1s at the end of the program right before the i. Ex: .../si/s|cs/c|ci/c/mcl0sl0<--input here-->i  You can also use an x in place of 8 1s as a side affect of golfing the program. There is a wrapper for easier testing below. Testing wrapper: Try it online! Ungolfed: Try it online! It does 2 divmods, one to separate into chests, stacks, and items, then again to convert to decimal. I could have it convert input from decimal as well, but I would also have to change all of the symbol names and add additional logic to keep it from breaking, so I'm not going to do that. Besides, I think unary is a recognized standard input for ///. # JavaScript (ES6) 71 bytes n=>[n/1728|0,(n/64|0)%27,n%64].map((a,i)=>a?a+'csi'[i]:'').join||'0i'  Snippet: f= n=>[n/1728|0,(n/64|0)%27,n%64].map((a,i)=>a?a+'csi'[i]:'').join||'0i' console.log(f(0)) // 0i console.log(f(1)) // 1i console.log(f(2)) // 2i console.log(f(62)) // 62i console.log(f(63)) // 63i console.log(f(64)) // 1s console.log(f(65)) // 1s1i console.log(f(66)) // 1s2i console.log(f(127)) // 1s63i console.log(f(128)) // 2s console.log(f(129)) // 2s1i console.log(f(200)) // 3s8i console.log(f(512)) // 8s console.log(f(1337)) // 20s57i console.log(f(1664)) // 26s console.log(f(1727)) // 26s63i console.log(f(1728)) // 1c console.log(f(1729)) // 1c1i console.log(f(1791)) // 1c63i console.log(f(1792)) // 1c1s console.log(f(1793)) // 1c1s1i console.log(f(4096)) // 2c10s console.log(f(5183)) // 2c26s63i console.log(f(5184)) // 3c console.log(f(5200)) // 3c16i console.log(f(9999)) // 5c21s15i console.log(f(385026)) // 222c22s2i console.log(f(1000000000)) // 578703c19s # Python 2, 82 bytes I converted Gabor Fekete's comment from above into a working example: lambda n:g(n/1728,"c")+g(n/64%27,"s")+g(n%64,"i")or"0i" g=lambda n,s:(n+s)*(n>0)  Try it online! # Batch, 347 335 283 246 234 202 199 191 189 bytes @set/al=%1,c=%1/1728,l-=c*1728,s=l/64,l-=s*64 @set c=%c%c @set s=%s%s @set i=%l%i @if %c%==0c set c= @if %s%==0s set s= @if %i%==0i set i= @if %c%%s%%i%.==. set i=0i @echo(%c%%s%%i%  • You do know you can use division and modulus in a set/a expression, don't you? – Neil Jun 7 '17 at 12:21 • @Neil I know, I'm working as the same way right now Jun 7 '17 at 12:22 • @Neil I'm just encountering an issue: if %c%==0 (set c=)else rem this codes gives me "(set is not expected" Jun 7 '17 at 12:23 • Huh, that should only happen if c is empty... – Neil Jun 7 '17 at 12:28 • JFTR my solution (two slightly different variations with the same length) is down to 122 bytes. – Neil Jun 7 '17 at 12:33 # dc, 76 bytes ?dddsf[1728/n99P]sc1728/0<c1728%ddd[64/n115P]si64/0<i[64%n105P]sy64%0<ylf0=y  Try it online! # Braingolf, 71 bytes V"isc"R#@!%>93*!*,>,>!/!*,>,$_-,>,>,/<$_<&,!?_v@R:>|!?_v@R:>|!?_v@R:>|;  Try it online! Not at all golfy, but it works # Mathematica, 155 bytes A=AppendTo;G={};P=Print;(z=Mod[t=Mod[#,1728],64];If[(x=⌊#/1728⌋)>0,A[G,{x,c}]];If[(y=⌊t/64⌋)>0,A[G,{y,s}]];If[z>0||#==0,A[G,{z,i}]];Row@Flatten@G)&  # PHP, 84 bytes <?=($c=($a=$argn)/1728^0)?$c.c:"",($s=$a/64%27)?$s.s:"",($i=$a%64)||$c+$s<1?$m.i:"";  Try it online! # PHP, 93 bytes $i-=64*$s=($i-=1728*$c=($i=$argn)/1728^0)/64^0;echo$c?$c.c:"",$s?$s.s:"",$i||$c+$s<1?$i.i:"";  Try it online! # T-SQL, 139 134 139 bytes Input is stored in column a of pre-existing table t. SELECT IIF(a=0,'0i',REPLACE(IIF(a<1728,'',STR(a/1728)+'c') +IIF(a%1728<64,'',STR(a%1728/64)+'s') +IIF(a%64=0,'',STR(a%64)+'i'),' ',''))FROM t  Line breaks for readability, not counted in byte total. Tested on MS SQL Server 2012. EDIT 1: Changed multiple REPLACE to IIF to save 5 bytes. Final REPLACE still necessary because STR annoyingly pads with spaces to 10 chars. EDIT 2: Fixed to follow the rules by using the approved input type for SQL, values stored in a named table. This cost bytes for the FROM, also requires SELECT instead of PRINT. Recovered 2 bytes by dropping an unnecessary parens. # PowerShell, 113 Bytes param($i)("$(($c=[math]::floor($i/1728)))c","")[!$c]+("$(($s=[math]::floor(($i%1728)/64)))s","")[!$s]+"$($i%64)i"


This hits a bunch of powershell's pain points very precisely.

[math]::Floor is required for this as PS does Bankers Rounding by default.

the PS Ternary also takes up a load of bytes compared to other languages, to do a simple null coallescence ($a="This";$a?$a:"That" or "This"?:"That") we need to do (($a="This"),"That")[$a-ne$null]

then we need to use all of these twice, and also add in another set of brackets in some places due to powershell's default operation order.

# Python 2, 77 bytes

lambda n:''.join(k+c for k,c in zip([n/1728,n/64%27,n%64],'csi')if k)or'0i'


Try it online!

# Jelly, 21 bytes

d64d1¦27FµTȯ3ịż“csi”\$


Try it online!

Like Jonathan Allan's essentially-the-same answer before it, this does seem too long.

Even more essentially the same:

# Jelly, 21 bytes

d64d1¦27Fż“csi”ẠƇȯ⁾0i


Try it online!