Pas tout à fait romain ternaire

23

Etant donné un entier n ≥ 0, sortez-le dans une notation base-3 non positionnelle, en utilisant des chiffres 139ABCDE…et un séparateur à 1 caractère. Chaque chiffre est une puissance consécutive de 3 et les chiffres sur le côté gauche du séparateur sont annulés, par exemple A931 | B → 81− (1 + 3 + 9 + 27) → 41 . Un chiffre ne peut apparaître qu'une seule fois.

Rigoureusement, que la valeur d'un chiffre soit:

  • sa valeur si le chiffre est 1, 3 ou 9
  • 27 si le chiffre est A
  • 3 fois la valeur du chiffre juste avant pour B..Z

Votre sortie doit satisfaire somme (valeur des chiffres à droite de |) - somme (valeur des chiffres à gauche de |) == entrée .

Exemples

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

Vous pouvez utiliser un caractère non espace différent comme séparateur. Vous êtes également autorisé à ne pas avoir de séparateur, auquel cas le plus grand chiffre commence la séquence positive. Vous n'avez pas besoin de gérer quelque chose de plus grand que 2 32 −1 ( PMIGDCBA9|RQNLH3).

Vous pouvez écrire un programme ou une fonction complète, et l'entrée et la sortie peuvent être fournies sur l'un des canaux habituels.

Il s'agit de , donc plus votre réponse est courte, mieux c'est!

FrownyFrog
la source
2
(apparenté ne signifie pas doublon, calme-toi)
Leaky Nun
8
Suis-je le seul qui n'a aucune idée de ce qui est demandé ici?
Shaggy
3
@Shaggy Exprime l'entrée comme une somme de puissances de 3 et de leurs négatifs. Mettez les négatifs à gauche de a |et les positifs à droite de celui-ci.
Martin Ender
2
@KevinCruijssen "non, la commande est gratuite." - OP
user202729
3
@ user202729 Ah, j'ai raté ce commentaire. Merci. Voilà ce qui arrive lorsque les règles sont dans les commentaires au lieu de modification dans le défi .. ( FrownyFrog , pourriez - vous ajouter cette règle au défi: soit l' ordre de chaque côté du séparateur est très bien?)
Kevin Cruijssen

Réponses:

5

Java 10, 120 113 112 109 107 102 octets

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 octets en utilisant une partie de l'astuce de la réponse JavaScript (ES6) de @Arnauld , en
changeant i=0et i++<1?49:i<3?51:i<4?57:i+61vers i=4et++i>9?i+55:i>8?57:++i+43 .
-6 octets grâce à @Arnauld directement, en se débarrassant de i.

Ordre de sortie: du plus haut au plus bas, |-délimiteur, du plus bas au plus haut.

Explication:

Essayez-le en ligne.

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
la source
1
Je pense que cela fonctionne: 103 octets
Arnauld
@Arnauld Nice one! Et -1 octet de plus en insérant rle corps de la boucle. Merci!
Kevin Cruijssen
@Arnauld Par curiosité, à quoi ressemblent les brute-forcers que vous avez utilisés pour ces deux derniers nombres magiques (quand vous l'avez toujours utilisé iet quand vous le réutilisez c)?
Kevin Cruijssen
1
Je l'ai déjà jeté ...: - / Mais voici le dernier . (Très inefficace, mais c'est OK pour de si petites valeurs.)
Arnauld
(De plus, je devrais vraiment tester si p=1et ne pas inclure *1dans le code si c'est le cas - même si cela ne conduit pas à une meilleure formule dans ce cas.)
Arnauld
5

Python 3 , 103 99 91 octets

4 octets grâce à Lynn.

8 octets grâce aux 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

Essayez-le en ligne!

Crédits à xnor pour la logique.

Leaky Nun
la source
5

JavaScript (ES6), 82 80 79 octets

Sorties en minuscules, ce qui devrait être très 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

Essayez-le en ligne!

Similaire à la réponse de Leaky "Ninja Master" Nun et également basée sur la réponse de xnor .

Conversion de chiffres

Nous commençons par k = 4 . Alors que k est inférieur à 9 , nous l'incrémentons deux fois à chaque itération et soustrayons 5 . Après cela, nous l'incrémentons une seule fois et le convertissons en 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
la source
2

Stax , 30 29 octets

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

Exécuter et déboguer

Port de ma réponse Stax dans convertisseur ternaire équilibré .

Explication

Utilise la version décompressée pour expliquer.

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
la source
1

C # .NET, 103 octets

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

Port de ma réponse Java 10 . Si un port direct (à l'exception de n->to n=>) avait été possible, j'aurais édité ma réponse Java avec ce polyglotte. Malheureusement cependant, c+=sur les caractères ou avoir c=49n'est pas possible en C #, d'où cette réponse lâche portée.

Essayez-le en ligne.

Kevin Cruijssen
la source
1

Perl 5 -p , 71 69 octets

n'utilise aucun séparateur. Les parties négatives et positives sont dans "l'ordre romain" (le plus grand chiffre en premier)

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

Essayez-le en ligne!

Ton Hospel
la source
1

Rubis , 87 84 82 octets

Enregistré 2 octets grâce à @ 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]*?|}

Essayez-le en ligne!

Rétablir Monica iamnotmaynard
la source
Je mentirais si je disais que je suis complètement ce code, mais je sais que vous raser 2 octets avec l' redoastuce: Essayez-le en ligne!
benj2240
1

J , 129 octets

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
)

Essayez-le en ligne!

Trop long, surtout pour un programme J ...

Explication:

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
la source
1

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

J'ai créé deux versions de cela, car la limite des défis d'une entrée max de travail de 0x100000000 semblait un peu étrange. Une version fonctionne avec des entiers 32 bits (qui ne respecte pas la limite pour des raisons évidentes), l'autre version fonctionne avec 64 bits (qui va bien au-delà de la limite donnée, au prix de 14 8 octets supplémentaires).

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

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

Ceci est identique sauf qu'il déclare que la variable entière est long (qui est 64 bits sur linux).

La longversion non golfée :

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

Comme vous pouvez le voir, cela fonctionne par décent récursif: si le reste est 1, le caractère respectif est ajouté à la chaîne de sortie après l'appel récursif. Si le reste est 2, la sortie est effectuée avant la récurrence. Dans ce cas, j'incrémente également la valeur de un pour gérer correctement le chiffre négatif. Cela a l'avantage supplémentaire de changer le reste à zéro, ce qui me permet d'utiliservalue%3 comme condition pour la post-récursion if.

Le résultat de la conversion est placé dans le tampon global. L' g()encapsuleur a pour tâche de mettre à zéro la chaîne résultante correctement et de réinitialiser le resultpointeur à son début (ce qui est également la façon dont g()"renvoie" le résultat).

Testez la longversion avec ce code:

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

Golf possible mais destructeur:

  • -4 octets: faites de la fonction un coup en supprimant la réinitialisation du pointeur dans g().

  • -5 octets: force l'appelant à effectuer la terminaison de chaîne, en renvoyant la chaîne sans terminaison bufferet la fin de la chaîne result.

cmaster
la source
1

Fusain , 36 octets

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

Essayez-le en ligne! Le lien est vers la version détaillée du code. Explication:

Nθ

Saisissez la valeur.

F³⊞υ⟦⟧

Poussez trois listes vides vers la liste vide prédéfinie.

F⁺139α«

Parcourez les caractères 139et l'alphabet majuscule.

⊞§υθι

Indexez cycliquement la liste des listes avec la valeur et poussez-y le caractère courant.

≔÷⊕θ³θ»

Divisez la valeur par 3 mais arrondissez-la en ajoutant 1 en premier.

F²«×|ι

Boucle deux fois. La deuxième fois, imprimez a |.

↑⊟υ

Chaque boucle nous pop la dernière entrée de la liste; la première fois, cela nous donne les entrées qui avaient un reste de 2(ce qui correspond à un chiffre ternaire équilibré de -1), tandis que la deuxième fois cela nous donne les entrées correspondant à un chiffre ternaire équilibré de 1. La matrice résultante s'imprime normalement verticalement, mais la rotation du sens d'impression vers le haut l'annule.

Neil
la source
0

Perl 5 , 92 89 octets

Inspiré par les réponses java et 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}

Essayez-le en ligne!

Avec un espace blanc:

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.
la source
0

PHP, 73 octets

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

port de la réponse de xnor , 53 octets

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

Exécuter en tant que pipe avec -nrou essayer en ligne .

Titus
la source