No es bastante ternario romano

23

Dado un número entero n ≥ 0, imprímalo en una notación de base-3 no posicional, usando dígitos 139ABCDE…y un separador de 1 carácter. Cada dígito es una potencia consecutiva de 3 y los dígitos en el lado izquierdo del separador se niegan, por ejemplo, A931 | B → 81− (1 + 3 + 9 + 27) → 41 . Un dígito puede aparecer solo una vez.

Rigurosamente, deje que el valor de un dígito sea:

  • su valor si el dígito es 1, 3 o 9
  • 27 si el dígito es A
  • 3 veces el valor del dígito justo delante de él para B...Z

Su salida debe satisfacer la suma (valor de dígitos a la derecha de |) - suma (valor de dígitos a la izquierda de |) == entrada .

Ejemplos

input     output
----------------
0         |
1         |1
7         3|91
730       |D1
9999      FEDC|GA9

Puede usar un carácter diferente que no sea espacio como separador. También se le permite no tener separador, en cuyo caso el dígito más grande comienza la secuencia positiva. No necesita manejar nada más grande que 2 32 −1 ( PMIGDCBA9|RQNLH3).

Puede escribir un programa o función completa, y la entrada y la salida se pueden proporcionar en cualquiera de los canales habituales.

Este es el , así que cuanto más corta sea su respuesta, mejor.

FrownyFrog
fuente
2
(relacionado no significa duplicado, cálmate)
Leaky Nun
8
¿Soy el único que no tiene idea de lo que se pregunta aquí?
Shaggy
3
@Shaggy Expresa la entrada como una suma de potencias de 3 y sus negativos. Coloca los negativos a la izquierda de a |y los positivos a la derecha.
Martin Ender
2
@KevinCruijssen "no, el pedido es gratis". - OP
user202729
3
@ user202729 Ah, perdí ese comentario. Gracias. Es lo que pasa cuando las reglas están en los comentarios en lugar de editado en el reto .. ( FrownyFrog , ¿Es posible añadir esa regla al desafío: cualquier orden a ambos lados de la delimitador está bien?)
Kevin Cruijssen

Respuestas:

5

Java 10, 120 113 112 109 107 102 bytes

n->{var r="|";for(char c=49;n++>0;c=(char)(c+=c>64?1:c*4%22%9),n/=3)r=n%3<1?c+r:n%3>1?r+c:r;return r;}

-3 bytes usando parte del truco de la respuesta de JavaScript de @Arnauld (ES6) ,
cambiando i=0y i++<1?49:i<3?51:i<4?57:i+61hacia i=4y ++i>9?i+55:i>8?57:++i+43.
-6 bytes gracias a @Arnauld directamente, al deshacerse de él i.

Orden de salida: de mayor a menor, |delimitador, de menor a mayor.

Explicación:

Pruébalo en línea.

n->{              // Method with integer parameter and String return-type
  var r="|";      //  Result-String, starting at the delimiter "|"
  for(char c=49;  //  Character, starting at '1'
      n++>0       //  Loop as long as `n` is larger than 0
                  //  Increasing it by 1 with `n++` at the start of every iteration
      ;           //    After every iteration:
       c=(char)(  //     Change character `c` to:
          c+=c>64?//      If the current `c` is an uppercase letter:
              1   //       Simpy go to the next letter using `c+1`
             :    //      Else:
              c*4%22%9),
                  //       Change '1' to '3', '3' to '9', or '9' to 'A' 
       n/=3)      //     Integer-divide `n` by 3
     r=           //     Change the result to:
       n%3<1?     //      If `n` modulo-3 is 0:
        c+r       //       Prepend the character to the result
       :n%3>1?    //      Else-if `n` modulo-3 is 2:
        r+c       //       Append the character to the result
       :          //      Else:
        r;        //       Leave `r` unchanged
   return r;}     //  Return the result-String
Kevin Cruijssen
fuente
1
Creo que esto funciona: 103 bytes
Arnauld
@Arnauld ¡Buena! Y -1 byte más al colocar rel cuerpo del bucle. ¡Gracias!
Kevin Cruijssen
@Arnauld Por curiosidad, ¿qué aspecto tienen los fuerza brutas que has usado para estos dos últimos números mágicos (cuando todavía los usaste iy cuándo los reutilizas c)?
Kevin Cruijssen
1
Ya lo tiré ...: - / Pero aquí está el último . (Muy ineficiente, pero está bien para valores tan pequeños.)
Arnauld
(Además, realmente debería probar si p=1incluirlo y no incluirlo *1en el código, aunque no conduzca a una mejor fórmula en ese caso.)
Arnauld
5

Python 3 , 103 99 91 bytes

4 bytes gracias a Lynn.

8 bytes gracias a los ovs.

def f(n,s="|",b=0):c=('139'+chr(b+62)*b)[b];return n and f(-~n//3,[s,s+c,c+s][n%3],b+1)or s

Pruébalo en línea!

Créditos a xnor por la lógica.

Monja permeable
fuente
5

JavaScript (ES6), 82 80 79 bytes

Salidas en minúsculas, que con suerte deberían estar bien.

f=(n,s=(k=4,'|'),c=++k>8?k.toString(36):++k-5)=>n?f(++n/3|0,[c+s,s,s+c][n%3]):s

Pruébalo en línea!

Similar a la respuesta de Nun Leaky "Ninja Master" y también basada en la respuesta de xnor .

Conversión de dígitos

Comenzamos con k = 4 . Mientras k es menor que 9 , lo incrementamos dos veces en cada iteración y restamos 5 . Después de eso, lo incrementamos solo una vez y lo convertimos a base-36.

  k  | ++k > 8       | k.toString(36) | ++k - 5  | result
-----+---------------+----------------+----------+--------
  4  | k=5  -> false |                | k=6 -> 1 | 1
  6  | k=7  -> false |                | k=8 -> 3 | 3
  8  | k=9  -> true  | '9'            |          | '9'
  9  | k=10 -> true  | 'a'            |          | 'a'
  10 | k=11 -> true  | 'b'            |          | 'b'
 ... | ...           | ...            | ...      | ...
Arnauld
fuente
2

Stax , 30 29 bytes

£└≤☻╘pÿ╖╡A[ô%æτ⌐}►ºôßHl4⌡π%^ 

Ejecutar y depurarlo

El puerto de mi respuesta Stax en Balanced Ternary Converter .

Explicación

Utiliza la versión desempaquetada para explicar.

139$VA+cz{;3%+,^3/~;wY1|I@'|ay2|I@L
139$VA+c                               "139AB...Z", make a copy
        z                              Empty array to store the digits
          {         w                  Do the following until 0.
           ;3%+                           Append `b%3` to the digits
                                          Originally, `b` is the input
              ,^3/                        `b=(b+1)/3`
                  ~;                       Make a copy of `b` which is used as the condition for the loop

                     Y                 Save array of digits in `y` for later use
                      1|I              Find index of 1's
                         @             Find the characters in "139AB...Z" corresponding to those indices
                          '|           A bar
                            ay2|I@     Do the same for 2's
                                  L    Join the two strings and the bar and implicit output
Weijun Zhou
fuente
1

C # .NET, 103 bytes

n=>{var r="|";for(var c='1';n++>0;c=(char)(c>64?c+1:c+c*4%22%9),n/=3)r=n%3<1?c+r:n%3>1?r+c:r;return r;}

Puerto de mi respuesta Java 10 . Si un puerto directo (excepto para n->a n=>) hubiera sido posible, habría editado mi respuesta Java con este políglota. Desafortunadamente, c+=en caracteres o tener c=49no es posible en C #, por lo tanto, esta respuesta suelta portada.

Pruébalo en línea.

Kevin Cruijssen
fuente
1

Perl 5 -p , 71 69 bytes

no utiliza separador Las partes negativa y positiva están en "orden romano" (el dígito más grande primero)

#!/usr/bin/perl -p
$n=$_}{s/@{[$n++%3]}\K/]/,$n/=3,y/?-]/>-]/for($_=21)x31;y/>?@12/139/d

Pruébalo en línea!

Ton Hospel
fuente
1

Rubí , 87 84 82 bytes

Guardado 2 bytes gracias a @ benj2240.

->n,s=[?1,?3,?9,*?A..?Z],r=[""]*3{r[-m=n%3]+=s.shift
n=n/3+m/2
n>0?redo:r[1,2]*?|}

Pruébalo en línea!

Restablecer a Monica iamnotmaynard
fuente
Mentiría si dijera que estoy siguiendo completamente este código, pero sé que ahorras 2 bytes con el redotruco: ¡ Pruébalo en línea!
benj2240
1

J 129 bytes

f=:3 :0
a=.'139',u:65+i.26
s=.'|'while.y>0 do.if.1=c=.3|y do.s=.s,{.a end.y=.<.y%3
if.c=2 do.s=.s,~{.a 
y=.1+y end.a=.}.a end.s
)

Pruébalo en línea!

Demasiado largo, especialmente para un programa J ...

Explicación:

f =: 3 : 0
   a =. '139',u:65+i.26   NB. a list '139ABC...Z'
   s =. '|'               NB. initialize the list for the result  
   while. y>0 do.         NB. while the number is greater than 0
      c =. 3|y            NB. find the remainder (the number modulo 3)
      y =. <.y%3          NB. divide the number by 3 
      if. c = 1 do.       NB. if the remainder equals 1
         s =. s,{.a       NB. Append the current power of 3 to the result
      end.
      if. c = 2 do.       NB. if the remainder equals 2 
         s =. s,~{.a      NB. prepends the result with the current power of 3
         y =. 1+y         NB. and increase the number with 1
      end.
      a =. }.a            NB. next power of 3 
   end.
   s                      NB. return the result  
)
Galen Ivanov
fuente
1

C, int: 138 123 bytes, long: 152 131 bytes

He creado dos versiones de esto, ya que el límite de los desafíos de una entrada máxima de trabajo de 0x100000000parecía un poco extraño. Una versión funciona con enteros de 32 bits (que falla el límite por razones obvias), la otra versión funciona con 64 bits (que va mucho más allá del límite dado, a un costo de 14 8 bytes adicionales).

Versión de 32 bits:

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;}

Versión de 64 bits:

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;}

Esto es idéntico, excepto que declara que la variable entera es long(que es de 64 bits en Linux).

La longversión sin golf :

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;
}

Como puede ver, esto funciona por recursivo decente: si el resto es 1, el carácter respectivo se agrega a la cadena de salida después de la llamada recursiva. Si el resto es 2, la salida se realiza antes del recursivo. En este caso, también incremento el valor en uno para manejar el dígito negativo correctamente. Esto tiene el beneficio adicional de cambiar el resto a cero, lo que me permite usarlo value%3como condición para el post-recursión if.

El resultado de la conversión se coloca en el búfer global. El g()reiniciador tiene el trabajo de cero terminando la cadena resultante correctamente, y para restablecer el resultpuntero a su inicio (que también es cómo g()"devuelve" el resultado).

Prueba la longversión con este código:

#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);
}

Posible más, pero golf destructivo:

  • -4 bytes: haga que la función sea única eliminando el reinicio del puntero g().

  • -5 bytes: obligan al llamante a realizar la terminación de la cadena, devolviendo la cadena sin terminación buffery el final de la cadena result.

cmaster
fuente
1

Carbón , 36 bytes

NθF³⊞υ⟦⟧F⁺139α«⊞§υθι≔÷⊕θ³θ»F²«×|ι↑⊟υ

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

Nθ

Ingrese el valor.

F³⊞υ⟦⟧

Empuje tres listas vacías a la lista vacía predefinida.

F⁺139α«

Recorre los caracteres 139y el alfabeto en mayúsculas.

⊞§υθι

Indice cíclicamente la lista de listas con el valor y envíele el carácter actual.

≔÷⊕θ³θ»

Divide el valor entre 3 pero redondea agregando 1 primero.

F²«×|ι

Bucle dos veces. La segunda vez, imprime a |.

↑⊟υ

Cada bucle sacamos la última entrada de la lista; la primera vez esto nos da las entradas que tenían un resto de 2(que corresponde a un dígito ternario balanceado de -1), mientras que la segunda vez nos da las entradas correspondientes a un dígito ternario balanceado de 1. La matriz resultante normalmente se imprimiría verticalmente, pero al girar la dirección de impresión hacia arriba se cancela.

Neil
fuente
0

Perl 5 , 92 89 bytes

Inspirado en las respuestas de Java y Python.

sub n{($n,$r,$c,@a)=(@_,'|',1,3,9,'A'..'Z');$n?n(int++$n/3,($c.$r,$r,$r.$c)[$n%3],@a):$r}

Pruébalo en línea!

Con algo de espacio en blanco:

sub n {
  ($n, $r, $c, @_) = (@_, "|", 1, 3, 9, 'A' .. 'Z');
  $n ? n( int++$n/3, ($c.$r, $r, $r.$c)[$n%3], @_)
     : $r
}
Kjetil S.
fuente
0

PHP, 73 bytes

for(;0|$n=&$argn;$n/=3)${$n++%3}.=_139[++$i]?:chr(61+$i);echo${2},_,${1};

respuesta del puerto de xnor , 53 bytes

for(;0|$n=&$argn;$n/=3)$s="0+-"[$n++%3].$s;echo$s??0;

Ejecutar como tubería -nro probarlos en línea .

Titus
fuente