Nicht ganz römisch ternär

23

Wenn eine Ganzzahl n ≥ 0 ist, geben Sie sie in einer nicht positionellen Basis-3-Notation aus, wobei Sie Ziffern 139ABCDE…und ein 1-Zeichen-Trennzeichen verwenden. Jede Ziffer ist eine fortlaufende Potenz von 3 und die Ziffern auf der linken Seite des Trennzeichens werden negiert, z. B. A931 | B → 81− (1 + 3 + 9 + 27) → 41 . Eine Ziffer darf nur einmal vorkommen.

Der Wert einer Ziffer sei streng genommen:

  • sein Wert, wenn die Ziffer 1, 3 oder 9 ist
  • 27 wenn die Ziffer ist A
  • 3-facher Wert der Ziffer davor für B..Z

Ihre Ausgabe sollte die Summe (Wert der Ziffern rechts von |) - Summe (Wert der Ziffern links von |) == Eingabe erfüllen .

Beispiele

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

Sie können ein anderes Zeichen ohne Leerzeichen als Trennzeichen verwenden. Sie dürfen auch kein Trennzeichen haben. In diesem Fall startet die größte Ziffer die positive Sequenz. Sie müssen nichts größer als 2 32 −1 ( PMIGDCBA9|RQNLH3) verarbeiten.

Sie können ein komplettes Programm oder eine komplette Funktion schreiben und die Ein- und Ausgabe kann auf jedem der üblichen Kanäle erfolgen.

Das ist . Je kürzer Ihre Antwort, desto besser!

FrownyFrog
quelle
2
(Verwandte bedeutet nicht duplizieren, beruhigen)
Undichte Nonne
8
Bin ich der einzige, der keine Ahnung hat, was hier gefragt wird?
Shaggy
3
@Shaggy Drücke die Eingabe als Summe der Potenzen von 3 und ihrer Negative aus. Setzen Sie die Negative links von a |und die Positiven rechts davon.
Martin Ender
2
@ KevinCruijssen "Nein, die Bestellung ist kostenlos." - OP
user202729
3
@ user202729 Ah, ich habe diesen Kommentar verpasst. Vielen Dank. Das ist, was passiert, wenn Regeln in den Kommentaren stehen, anstatt in der Herausforderung bearbeitet zu werden. ( FrownyFrog , können Sie diese Regel zur Herausforderung hinzufügen: Jede Reihenfolge auf beiden Seiten des Begrenzers ist in Ordnung?)
Kevin Cruijssen

Antworten:

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 durch Verwendung eines Teils des Tricks von @Arnauld 's JavaScript (ES6) zum Antworten ,
Ändern von i=0und i++<1?49:i<3?51:i<4?57:i+61nach i=4und ++i>9?i+55:i>8?57:++i+43.
-6 Bytes dank @Arnauld direkt durch Loswerdeni .

Ausgabereihenfolge: Höchste bis niedrigste |, niedrigste bis höchste Grenze.

Erläuterung:

Probieren Sie es online aus.

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
quelle
1
Ich denke, das funktioniert: 103 Bytes
Arnauld
@ Arnauld Schöne! Und -1 weiteres Byte durch Einfügen rdes Schleifenkörpers. Vielen Dank!
Kevin Cruijssen
@Arnauld Aus Neugierde, wie sehen die Brute-Forcer aus, die Sie für die letzten beiden magischen Zahlen verwendet haben (wenn Sie sie noch verwendet ihaben und wenn Sie sie wiederverwenden c)?
Kevin Cruijssen
1
Ich habe es schon weggeworfen ...: - / Aber hier ist das letzte . (Sehr ineffizient, aber das ist in Ordnung für so kleine Werte.)
Arnauld
(Außerdem sollte ich wirklich testen, ob p=1und nicht *1in den Code aufzunehmen, wenn dies der Fall ist - auch wenn dies in diesem Fall nicht zu einer besseren Formel führt.)
Arnauld
5

Python 3 , 103 99 91 Bytes

4 Bytes dank Lynn.

8 Bytes dank 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

Probieren Sie es online!

Dank an xnor für die Logik.

Undichte Nonne
quelle
5

JavaScript (ES6), 82 80 79 Byte

Ausgaben in Kleinbuchstaben, die hoffentlich in Ordnung sein sollten.

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

Probieren Sie es online!

Ähnlich der Antwort von Leaky "Ninja Master" Nun und auch basierend auf der Antwort von xnor .

Ziffernkonvertierung

Wir beginnen mit k = 4 . Während k kleiner als 9 ist , erhöhen wir es zweimal bei jeder Iteration und subtrahieren 5 . Danach erhöhen wir es nur einmal und konvertieren es in 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
quelle
2

Stax , 30 29 Bytes

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

Führen Sie es aus und debuggen Sie es

Port meiner Stax-Antwort in Balanced Ternary Converter .

Erläuterung

Verwendet die entpackte Version, um zu erklären.

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

Port meiner Java 10 Antwort . Wenn ein direkter Port (außer n->to n=>) möglich gewesen wäre, hätte ich meine Java-Antwort mit diesem Polyglot bearbeitet. Leider jedoch c+=auf Charaktere oder mitc=49 in C # nicht möglich, daher diese lose portierte Antwort.

Probieren Sie es online aus.

Kevin Cruijssen
quelle
1

Perl 5 -p , 71 69 Bytes

verwendet kein Trennzeichen. Der negative und der positive Teil sind in "römischer Reihenfolge" (größte Ziffer zuerst)

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

Probieren Sie es online!

Tonne Hospel
quelle
1

Ruby , 87 84 82 Bytes

2 Bytes dank @ benj2240 gespeichert.

->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]*?|}

Probieren Sie es online!

Setzen Sie Monica iamnotmaynard wieder ein
quelle
Ich würde lügen, wenn ich sagen würde, dass ich diesem Code vollständig folge, aber ich weiß, dass Sie mit dem redoTrick 2 Bytes abschneiden : Probieren Sie es online aus!
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
)

Probieren Sie es online!

Zu langwierig, besonders für ein J-Programm ...

Erläuterung:

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

C int: 138 123 Bytes long: 152 131 Bytes

Ich habe zwei Versionen davon erstellt, da die Grenze der Herausforderungen bei einem maximalen Arbeitseingang von 0x100000000etwas seltsam erschien. Eine Version arbeitet mit 32-Bit-Ganzzahlen (die aus offensichtlichen Gründen das Limit verfehlen), die andere Version arbeitet mit 64 Bit (die weit über das angegebene Limit hinausgehen und 14 8 zusätzliche Bytes kosten ).

32 Bit Version:

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 Bit Version:

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

Dies ist identisch mit der Ausnahme, dass die Ganzzahlvariable als long(64-Bit unter Linux) deklariert wird.

Die ungolfed longVersion:

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

Wie Sie sehen, funktioniert dies bei rekursivem Anstand: Wenn der Rest 1 ist, wird das entsprechende Zeichen nach dem rekursiven Aufruf an die Ausgabezeichenfolge angehängt. Wenn der Rest 2 ist, wird die Ausgabe vor der Rekursion ausgeführt. In diesem Fall erhöhe ich auch den Wert um eins, um die negative Ziffer richtig zu behandeln. Dies hat den zusätzlichen Vorteil, dass der Rest auf Null gesetzt wird und ich ihn value%3als Bedingung für die Nachrekursion verwenden kann, wenn.

Das Ergebnis der Konvertierung wird in den globalen Puffer gestellt. Der g()Wrapper hat die Aufgabe, die resultierende Zeichenkette korrekt mit Null zu beenden und den resultZeiger auf den Anfang zurückzusetzen (was auch so ist)g() das Ergebnis "zurückgegeben" wird).

Testen Sie die longVersion mit diesem 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);
}

Mögliches weiteres, aber zerstörerisches Golfen:

  • -4 Bytes: Machen Sie die Funktion zu einem One-Shot, indem Sie den Zeiger entfernen, der in zurückgesetzt wurde g().

  • -5 Bytes: Der Aufrufer wird gezwungen, die String-Terminierung durchzuführen, wobei der String ohne Terminierung in bufferund das Ende des Strings in zurückgegeben werden result.

cmaster
quelle
1

Kohle , 36 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:

Nθ

Geben Sie den Wert ein.

F³⊞υ⟦⟧

Verschieben Sie drei leere Listen in die vordefinierte leere Liste.

F⁺139α«

Durchlaufen Sie die Zeichen 139und das Großbuchstaben.

⊞§υθι

Indizieren Sie zyklisch die Liste der Listen mit dem Wert und verschieben Sie das aktuelle Zeichen dorthin.

≔÷⊕θ³θ»

Teilen Sie den Wert durch 3, runden Sie ihn jedoch durch Hinzufügen von 1.

F²«×|ι

Schleife zweimal. Drucken Sie beim zweiten Mal a |.

↑⊟υ

In jeder Schleife wird der letzte Eintrag aus der Liste eingefügt. Beim ersten Mal erhalten wir die Einträge, die einen Rest von 2(der einer ausgeglichenen ternären Ziffer von entspricht -1) hatten, während beim zweiten Mal die Einträge erhalten werden, die einer ausgeglichenen ternären Ziffer von entsprechen 1. Das resultierende Array wird normalerweise vertikal gedruckt, aber durch Drehen der Druckrichtung nach oben wird dies abgebrochen.

Neil
quelle
0

Perl 5 , 92 89 Bytes

Inspiriert von den Java- und Python-Antworten.

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}

Probieren Sie es online!

Mit etwas Leerraum:

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

PHP, 73 Bytes

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

Port der Antwort von xnor , 53 Bytes

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

Laufen Sie als Pipe mit -nroder probieren Sie sie online aus .

Titus
quelle