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.


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

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

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'
 ... | ...           | ...            | ...      | ...



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

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.


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!



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  
)

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.


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.



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
}

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 .

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.