Most efficient cubifier
Lua, Score: 85.91 13.50 13.20 12.70 9.41 9.32 9.83 9.66 9.12 9.06 8.03 (Average)
-- Get input
local inp = io.read("*a")
local out = ""
local faces = { [5] = 45, [4] = 36, [3] = 27, [2] = 18, [1] = 9 }
local lastChar = nil
-- Mode the program is in
-- 2 = not set (needs :), 1 = just set (needs +), 0 = normal
local mode = 1;
for i = 1, inp:len() do
-- Character value at current position
local c = string.byte(inp, i)
if c == lastChar then
-- Repeat character
out = out .. "6"
elseif c % 9 == 0 and c <= 45 then
if #out == 0 then
out = out .. "@"
end
out = out .. (c / 9)
else
local c2 = c
-- Handle if difference from lastChar is divisible by 9
if lastChar and (c - lastChar) % 9 == 0 then
local difference = c - lastChar
if difference > 0 then
out = out .. "+"
else
out = out .. "-"
difference = difference * -1
end
for index = 5, 1, -1 do
local face = faces[index]
while difference >= face do
difference = difference - face
out = out .. index
end
end
c = 0
end
-- Handle anything not divisible by 9
local extra = c % 9
if extra > 0 then
-- Try to optimize by dividing by 9, if possible
if lastChar and math.floor(lastChar / 9) == extra then
out = out .. "/1"
mode = 1
extra = 0
else
while extra > 0 do
local n = extra > 5 and 5 or extra
if mode == 2 then
out = out .. ":"
mode = 1
elseif mode == 1 then
out = out .. "+"
mode = 0
end
out = out .. n
extra = extra - n
end
out = out .. "/1"
mode = 1
end
c = c - (c % 9)
end
-- Handle anything divisible by 9
for index = 5, 1, -1 do
local face = faces[index]
while c >= face do
if mode == 2 then
out = out .. ":"
mode = 1
elseif mode == 1 then
out = out .. "+"
mode = 0
end
c = c - face
out = out .. index
end
end
out = out .. "@6"
lastChar = c2
end
mode = 2
end
print(out)
Try it online!
Okay, I don't think I can optimize this anymore.
This version iterates through each character, adding c % 9 (where c is the character's decimal value) by doing :5+2/1
, then adds the parts divisible by 9 by adding that face's value. For example: :2/1+551@
to print "e", where :2/1
adds 2, +551
adds 99 (9 * (5 + 5 + 1), or 9 * 11), and @
prints the output. Input is read with io.read()
.
Optimizations include directly adding/subtracting after printing if the difference between characters is a multiple of 9, dividing the current value if possible rather than setting c % 9 from scratch, and repeating characters by printing the current value again rather than recalculating it. Additionally, I've implemented Kamil's method of instantly printing any face that already contains the target value, and MD XF's suggestion to not use :
at the beginning, but instead just start with a +
.
Cubically, Score: 86.98
U3D1R3L1F3B1U1D3~:7+1(-1@3(-1%1)6:1+3111@6%1-31111+004@6:1+11111%6:1+45@6:1-1%6~:7+1)6
Try it online!
Turns out, all you need is conditional loops, a face equal to 1, and consistent End-Of-Input behavior.
U3D1R3L1F3B1U1D3 set LEFT face sum to 1
~:7 read input, set notepad to input
+1 add 1 to notepad
( open loop that can always be jumped to
-1 subtract 1 from notepad
@3 print RIGHT face (ASCII 43 '+')
## the following mechanism gets the output program's ##
## notepad to the current inputted ASCII value: ##
( open loop that can always be jumped to
-1 subtract 1 from notepad
%1 print '1'
)6 jump back to loop while notepad is nonzero
## the following mechanism prints "/1@6:1" ##
:1+3111@6 set notepad to 47, print (ASCII 47 '/')
%1 print LEFT face print (integer '1')
-31111+004@6 set notepad to 64, print (ASCII 64 '@')
:1+11111%6 set notepad to 6, print (integer 6)
:1+45@6 set notepad to 58, print (ASCII 58 ':')
:1-1%6 set notepad to 0, print (integer 1)
~ read input
:7+1 set notepad to input plus 1, so EOF changes to zero
)6 loop if notepad is truthy
The adding/subtracting of the LEFT face is to get the loop to end when EOF is read.
C# (.NET Core), Score: 129.98 11.73 10.82 9.62 10.33 10.32 10.20
-1.2 point from MD XF's suggestion to use @6666...
instead of @6@6@6@6...
for repeating character, and superior initialization sequence
static void Main()
{
List<byte> input = new List<byte>();
int inChar = Console.Read();
while (inChar != -1)
{
input.Add((byte)inChar);
inChar = Console.Read();
}
Console.Write("U3D1R3L1F3B1U1D3");
byte[] sides = new byte[] { 20, 1, 14, 43, 24, 33 };
byte currentChar = 0;
if(currentChar == input[0] || sides.Contains(input[0])) Console.Write("@");
foreach (byte character in input)
{
if (currentChar == character)
{
Console.Write("6");
continue;
}
if (sides.Contains(character))
{
Console.Write(Array.IndexOf(sides, character));
continue;
}
if (currentChar < character)
{
Console.Write("+");
while (currentChar < character)
{
byte nextAdd = sides.Where(s => s + currentChar <= character).Max();
currentChar = (byte)(currentChar + nextAdd);
Console.Write(Array.IndexOf(sides, nextAdd));
}
}
if (currentChar > character)
{
Console.Write("-");
while (currentChar > character)
{
byte nextSub = sides.Where(v => currentChar - v >= character).Max();
currentChar = (byte)(currentChar - nextSub);
Console.Write(Array.IndexOf(sides, nextSub));
}
}
Console.Write("@6");
}
}
Try it online!
My newest version actually does some manipulation of the cube! Yay!
That first Console.Write
up there is a fixed manipulation MD XF worked out that creates this cube:
242
202
242
000131555313
010121535343
000131555313
424
454
424
The significance of this cube is that one of its sides has a sum of 1, allowing manipulations of the Notepad on a smaller scale than multiples of nine, and in particular it simplifies relative movement rather than needing to start from zero each character; in this algorithm both addition and subtraction are used to take the shortest path between characters.
MD XF's version of the initialization causes side 2 to have a sum of 14, which saves many bytes of output for ASCII distances between 14 and 20.
Now can handle inputs with internal newlines, Console.Read() gets individual characters until End of File; see the TIO link which should have the input
Hello,
World!
Shaved a couple fractions of a point by immediately outputting a character if its ASCII value just happens to already exist on a side.
Test Script courtesy of MDXF
Previous submission here and explanation:
This is kinda boring, but as far as I can tell it works. Admittedly I only tried Hello, World!
but I ran the output in the TIO Cubically interpreter and it output "Hello, World!" so I assumed it works.
Rather than actually manipulating the cube at all, the notepad is simply incremented by the sum of the 1 face (9) repeatedly until it has the right value for each character, then prints it.