C int
: 138 123 байта long
: 152 131 байта
Я создал две версии этого, так как предел трудностей при максимальном рабочем входе 0x100000000
казался немного странным. Одна версия работает с 32-битными целыми числами (что по понятным причинам выходит за пределы ограничения), другая версия работает с 64-битными значениями (что выходит за рамки заданного ограничения за счет 14 8 дополнительных байтов).
32-битная версия:
char b[22],*r=b;f(v,l)char*l;{v%3>1?*r++=*l,v++:0;v&&f(v/3,l+1);v%3?*r++=*l:0;}g(v){f(v,"139ABCDEFGHIJKLMNOPQR");*r=0;r=b;}
64-битная версия:
char b[22],*r=b;f(long v,char*l){v%3>1?*r++=*l,v++:0;v&&f(v/3,l+1);v%3?*r++=*l:0;}g(long v){f(v,"139ABCDEFGHIJKLMNOPQR");*r=0;r=b;}
Это идентично, за исключением того, что оно объявляет целочисленную переменную long
(которая в Linux равна 64 битам).
Негольфированная long
версия:
char buffer[22],*result=buffer;
f(long value,char*letter){
if(value%3>1){
*result++=*letter,value++;
}
if(value){
f(value/3,letter+1);
}
if(value%3){
*result++=*letter;
}
}
g(long value){
f(value,"139ABCDEFGHIJKLMNOPQR");
*result=0;
result=buffer;
}
Как вы можете видеть, это работает по принципу рекурсивного приличия: если остаток равен 1, соответствующий символ добавляется к выходной строке после рекурсивного вызова. Если остаток равен 2, вывод выполняется перед рекурсией. В этом случае я также увеличиваю значение на единицу, чтобы правильно обрабатывать отрицательную цифру. Это имеет дополнительное преимущество, заключающееся в изменении остатка на ноль, что позволяет мне использовать его value%3
как условие для пострекурсии if.
Результат преобразования помещается в глобальный буфер. g()
Обертка имеет работу нуля завершающие получившуюся строку правильно, и чтобы сбросить result
указатель на его начало (что и как g()
«возвращает» результат).
Проверьте long
версию с этим кодом:
#include <stdio.h>
char b[22],*r=b;f(long v,char*l){v%3>1?*r++=*l,v++:0;v&&f(v/3,l+1);v%3?*r++=*l:0;}g(long v){f(v,"139ABCDEFGHIJKLMNOPQR");*r=0;r=b;}
void printConversion(long value) {
g(value);
printf("%ld: %s\n", value, r);
}
int main() {
for(long i = 0; i <= 40; i++) {
printConversion(i);
}
printConversion(0x7fffffff);
printConversion(0xffffffffu);
printConversion(0x100000000);
}
Возможно дальнейшее, но деструктивное гольфирование:
-4 байта: сделать функцию однократной, удалив сброс указателя в g()
.
-5 байт: заставить вызывающего выполнить завершение строки, возвращая строку без завершения в buffer
и конец строки в result
.