Не зовсім римський тернар


23

З огляду на ціле число n ≥ 0, виведіть його у непозиційній нотації base-3, використовуючи цифри 139ABCDE…та роздільник 1 символів. Кожна цифра є послідовною силою 3, а цифри з лівого боку роздільника заперечуються, наприклад A931 | B → 81− (1 + 3 + 9 + 27) → 41 . Цифра може з’являтися лише один раз.

Суворо, нехай значення цифри буде:

  • його значення, якщо цифра дорівнює 1, 3 або 9
  • 27, якщо цифра дорівнює A
  • 3 рази більше значення цифри прямо перед ним для B..Z

Ваш вихід повинен відповідати сумі (значення цифр праворуч від |) - сума (значення цифр зліва від |) == введення .

Приклади

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

Ви можете використовувати інший непробільний символ як роздільник. Вам також дозволяється не мати роздільника, і в цьому випадку найбільша цифра починає позитивну послідовність. Вам не потрібно обробляти щось більше, ніж 2 32 −1 ( PMIGDCBA9|RQNLH3).

Ви можете написати повну програму або функцію, а введення та вихід можуть бути надані на будь-якому з звичайних каналів.

Це , тому чим коротше ваша відповідь, тим краще!


2
(споріднене не означає дублікат, заспокойтеся)
Leaky Nun

8
Я єдиний, хто не має поняття, про що тут питають?
Кудлатий

3
@Shaggy Висловіть дані як суму повноважень 3 та їх негативів. Поставте мінуси зліва |та позитиви праворуч від нього.
Мартін Ендер

2
@KevinCruijssen "ні, замовлення безкоштовне". - OP
користувач202729

3
@ user202729 Ах, пропустив цей коментар. Спасибі. Ось що відбувається, коли правила в коментарях замість редагуються на виклик .. ( FrownyFrog , чи можете ви додати це правило до виклику: будь-який порядок з обох боків роздільника є нормальним?)
Кевін Круїйссен

Відповіді:


5

Java 10, 120 113 112 109 107 102 102 байт

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 байти, використовуючи частину трюку @Arnauld JavaScript (ES6) відповіді «s ,
змінюється i=0і i++<1?49:i<3?51:i<4?57:i+61до i=4і ++i>9?i+55:i>8?57:++i+43.
-6 байт завдяки @Arnauld безпосередньо, позбувшись i.

Порядок виводу: Найвищий-до-нижчий, |-делімітер, найнижчий-найвищий.

Пояснення:

Спробуйте в Інтернеті.

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
Я думаю, це працює: 103 байти
Арнольд

@Arnauld Приємний! І ще -1 байт, вставивши rв корпус петлі. Спасибі!
Кевін Кройсейсен

@Arnauld З цікавості, як виглядають грубі сили, які ви використовували для цих двох останніх магічних чисел (коли ви все ще використовували iта коли повторно користуєтесь c)?
Кевін Круїссен

1
Я вже його викинув ...: - / Але ось останній . (Дуже неефективно, але це нормально для таких малих значень.)
Арнольд

(Крім того, я дійсно повинен перевірити, чи p=1не включати його *1до коду, якщо він є - навіть якщо це не призводить до кращої формули в такому випадку.)
Арнольд


5

JavaScript (ES6), 82 80 79 байт

Виходи малі, що, сподіваємось, буде добре.

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

Спробуйте в Інтернеті!

Подібний до відповіді Лена "Майстра ніндзя", і також заснований на відповіді xnor .

Перетворення цифр

Почнемо з k = 4 . Хоча k менше 9 , ми збільшуємо його двічі на кожній ітерації і віднімаємо 5 . Після цього ми збільшуємо його лише один раз і перетворюємо на базу-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

Стакс , 30 29 байт

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

Запустіть і налагоджуйте його

Порт моєї відповіді на Stax у збалансованому термінальному перетворювачі .

Пояснення

Використовує розпаковану версію для пояснення.

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 байти

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

Порт моєї відповіді на Java 10 . Якщо прямий порт (за винятком n->до n=>) було б можливо, я б відредагував мій відповідь на Java з допомогою цього поліглота. На жаль, c+=щодо символів або c=49неможливості в C #, звідси і ця вільна відповідь.

Спробуйте в Інтернеті.



1

Рубі , 87 84 82 байт

Збережено 2 байти завдяки @ 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]*?|}

Спробуйте в Інтернеті!


Я б брехав, якби сказав, що я повністю дотримуюся цього коду, але я знаю, що ти збрив 2 байти з redoхитрістю: Спробуйте в Інтернеті!
benj2240

1

J , 129 байт

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
)

Спробуйте в Інтернеті!

Занадто тривалий, особливо для програми J ...

Пояснення:

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

З int: 138 123 байт, long: 152 131 байт

Я створив дві версії цього, так як межа викликів робочого максимального вкладу 0x100000000здавався трохи дивним. Одна версія працює з 32-бітовими цілими числами (що не відповідає ліміту з очевидних причин), інша версія працює з 64 бітами (що виходить за межі заданого ліміту, ціною 14 8 додаткових байт).

32-розрядна версія:

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-розрядна версія:

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

Це ідентично, за винятком того, що він оголошує цілу змінну рівним long(що становить 64 біти в Linux).

Негольована longверсія:

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

Як бачите, це працює за допомогою рекурсивно пристойного: Якщо залишок дорівнює 1, відповідний символ додається до вихідного рядка після рекурсивного виклику. Якщо залишок дорівнює 2, висновок виконується перед повторюваним. У цьому випадку я також збільшую значення на одиницю, щоб правильно обробити негативну цифру. Це має додаткову перевагу від зміни решти до нуля, що дозволяє мені використовувати value%3як умову післярекурсії, якщо.

Результат перетворення розміщується в глобальному буфері. g()Обгортка має роботу нуля завершальні вийшла рядок правильно, і щоб скинути resultпокажчик на його початок (що і як g()«повертає» результат).

Тестуйте longверсію за допомогою цього коду:

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

Можливий подальший, але руйнівний гольф:

  • -4 байти: перетворіть функцію в один кадр, видаливши скидання вказівника g().

  • -5 байт: змусити абонента виконати завершення рядка, повернувши рядок без завершення в bufferі кінець рядка в result.


1

Вугілля деревне , 36 байт

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

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

Nθ

Введіть значення.

F³⊞υ⟦⟧

Натисніть три порожні списки до попередньо визначеного порожнього списку.

F⁺139α«

Проведіть цикл через символи 139та алфавіт.

⊞§υθι

Циклічно індексуйте список списків із значенням і натисніть на нього поточний символ.

≔÷⊕θ³θ»

Розділіть значення на 3, але округлете його, додавши спочатку 1.

F²«×|ι

Два рази петлю. Вдруге надрукуйте а |.

↑⊟υ

Кожен цикл ми виводимо останній запис зі списку; перший раз це дає нам записи, які мали залишок 2(що відповідає збалансованому потрійному розряду -1), а вдруге це дає нам записи, що відповідають збалансованому потрійному розряду 1. Отриманий масив зазвичай друкується вертикально, але повернення напрямку друку вгору скасовує це.



0

Perl 5 , 92 89 байт

Натхненний відповідями java та 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}

Спробуйте в Інтернеті!

З пробілом:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.