Não muito romano Ternário

23

Dado um número inteiro n ≥ 0, imprima-o em uma notação de base 3 não posicional, usando dígitos 139ABCDE…e um separador de 1 caractere. Cada dígito é uma potência consecutiva de 3 e os dígitos no lado esquerdo do separador são negados, por exemplo, A931 | B → 81− (1 + 3 + 9 + 27) → 41 . Um dígito pode aparecer apenas uma vez.

Rigorosamente, permita que o valor de um dígito seja:

  • seu valor se o dígito for 1, 3 ou 9
  • 27 se o dígito for A
  • 3 vezes o valor do dígito logo antes dele para B..Z

Sua saída deve satisfazer a soma (valor dos dígitos à direita da |) - soma (valor dos dígitos à esquerda da |) == entrada .

Exemplos

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

Você pode usar um caractere diferente do espaço como separador. Também é permitido que você não tenha separador; nesse caso, o dígito maior inicia a sequência positiva. Você não precisa lidar com nada maior que 2 32 −1 ( PMIGDCBA9|RQNLH3).

Você pode escrever um programa ou função completo, e entrada e saída podem ser fornecidas em qualquer um dos canais habituais.

Isso é , portanto, quanto menor a sua resposta, melhor!

FrownyFrog
fonte
2
(relacionado não significa duplicar, acalme-se) #
Leaky Nun 28/03
8
Eu sou o único que não tem idéia do que está sendo perguntado aqui?
Shaggy
3
@ Shaggy Expresse a entrada como uma soma de potências de 3 e seus negativos. Coloque os negativos à esquerda de a |e os positivos à direita.
Martin Ender
2
@KevinCruijssen "não, o pedido é gratuito." - OP
user202729
3
@ user202729 Ah, perdi esse comentário. Obrigado. É o que acontece quando as regras são nos comentários em vez de editados no desafio .. ( FrownyFrog , você poderia acrescentar que regra para o desafio: qualquer ordem em ambos os lados do delimitador é bom?)
Kevin Cruijssen

Respostas:

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 do truque da resposta JavaScript (ES6) do @Arnauld ,
alterando i=0e i++<1?49:i<3?51:i<4?57:i+61para i=4e ++i>9?i+55:i>8?57:++i+43.
-6 bytes graças a @Arnauld diretamente, livrando-se de i.

Ordem de saída: maior para o menor, |-delimitador, do menor para o maior.

Explicação:

Experimente online.

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
fonte
1
Eu acho que isso funciona: 103 bytes
Arnauld
@ Arnauld Nice one! E mais -1 byte, inserindo ro corpo do loop. Obrigado!
Kevin Cruijssen 29/03
@Arnauld Por curiosidade, como são os forçadores-brutos que você usou para esses dois últimos números mágicos (quando você ainda usa ie quando reutiliza c)?
Kevin Cruijssen 29/03
1
Eu já joguei fora ...: - / Mas aqui está o último . (. Muito ineficiente, mas isso é OK para tais valores pequenos)
Arnauld
(Além disso, eu realmente deve testar se p=1e não incluem *1no código, se é -. Mesmo que ele não leva a uma melhor fórmula, nesse caso)
Arnauld
5

Python 3 , 103 99 91 bytes

4 bytes graças a Lynn.

8 bytes graças a 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

Experimente online!

Créditos ao xnor pela lógica.

Freira Furada
fonte
5

JavaScript (ES6), 82 80 79 bytes

Saídas em minúsculas, o que deve ser bom.

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

Experimente online!

Semelhante à resposta da freira "Mestre Ninja" da Leaky e também com base na resposta do xnor .

Conversão de dígitos

Começamos com k = 4 . Enquanto k é menor que 9 , nós o incrementamos duas vezes a cada iteração e subtraímos 5 . Depois disso, o incrementamos apenas uma vez e o convertemos em 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
fonte
4

Geléia , 26 bytes

‘:3Ɗ⁹С‘%3ẹЀ0,2ị139D;ØA¤Y

Experimente online!

Use uma nova linha como separador.

user202729
fonte
26 bytes
Freira vazada
25 bytes
Freira vazada
2

Stax , 30 29 bytes

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

Execute e depure

Porta da minha resposta Stax no Balanced Ternary Converter .

Explicação

Usa a versão descompactada 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
fonte
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;}

Porta da minha resposta do Java 10 . Se uma porta direta (exceto n->a n=>) teria sido possível, gostaria de ter editado a minha resposta Java com este poliglota. Infelizmente, c+=no entanto, em caracteres ou ter c=49não é possível em C #, portanto, esta resposta portada frouxa.

Experimente online.

Kevin Cruijssen
fonte
1

Perl 5 -p , 71 69 bytes

não usa separador. As partes negativa e positiva estão em "ordem romana" (primeiro dígito maior)

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

Experimente online!

Ton Hospel
fonte
1

Ruby , 87 84 82 bytes

Economizou 2 bytes graças 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]*?|}

Experimente online!

Restabelecer Monica iamnotmaynard
fonte
Eu mentiria se dissesse que estou seguindo completamente esse código, mas sei que você economiza 2 bytes com o redotruque: Experimente online!
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
)

Experimente online!

Muito longo, especialmente para um programa J ...

Explicação:

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
fonte
1

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

Eu criei duas versões disso, pois o limite dos desafios de uma entrada máxima de trabalho 0x100000000parecia um pouco estranho. Uma versão trabalha com números inteiros de 32 bits (que falham no limite por razões óbvias), a outra versão trabalha com 64 bits (que vai muito além do limite especificado, ao custo de 14 8 bytes extras).

Versão 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;}

Versão 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;}

Isso é idêntico, exceto que declara que a variável inteira é long(que é de 64 bits no linux).

A longversão não destruída :

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 você pode ver, isso funciona de forma recursiva decente: se o restante for 1, o respectivo caractere será anexado à sequência de saída após a chamada recursiva. Se o restante for 2, a saída é executada antes da recorrência. Nesse caso, eu também incremento o valor em um para manipular o dígito negativo corretamente. Isso tem o benefício adicional de alterar o restante para zero, permitindo que eu use value%3como condição para a pós-recursão se.

O resultado da conversão é colocado no buffer global. O g()wrapper tem o trabalho de zero, finalizando a sequência resultante corretamente e redefinindo o resultponteiro para o início (que também é como g()"retorna" o resultado).

Teste a longversão com 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);
}

Possível ainda mais, mas destrutivo golfe:

  • -4 bytes: torne a função única, removendo o ponteiro de reinicialização g().

  • -5 bytes: força o chamador a executar o término da sequência, retornando a sequência sem terminação buffere o final da sequência em result.

cmaster
fonte
1

Carvão , 36 bytes

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

Experimente online! Link é a versão detalhada do código. Explicação:

Nθ

Insira o valor.

F³⊞υ⟦⟧

Envie três listas vazias para a lista vazia predefinida.

F⁺139α«

Faça um loop entre os caracteres 139e o alfabeto maiúsculo.

⊞§υθι

Indexe ciclicamente a lista de listas com o valor e envie o caractere atual a ele.

≔÷⊕θ³θ»

Divida o valor por 3, mas arredonde-o adicionando 1 primeiro.

F²«×|ι

Loop duas vezes. Na segunda vez, imprima a |.

↑⊟υ

Cada loop aparece a última entrada da lista; a primeira vez que isso nos fornece as entradas que tinham um restante de 2(que corresponde a um dígito ternário balanceado de -1), enquanto a segunda vez isso nos dá as entradas correspondentes a um dígito ternário balanceado de 1. A matriz resultante normalmente imprime verticalmente, mas girar a direção da impressão para cima cancela isso.

Neil
fonte
0

Perl 5 , 92 89 bytes

Inspirado nas respostas java e 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}

Experimente online!

Com algum espaço em branco:

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.
fonte
0

PHP, 73 bytes

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

porta da resposta do xnor , 53 bytes

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

Execute como pipe -nrou experimente-os online .

Titus
fonte