Мінус, плюс, часи, експоненція?


26

Це CMC (чат-міні-виклик), який я трохи більше тому опублікував у нашій кімнаті для спілкування «Дев'ятий байт» .

Змагання

Враховуючи додатне ціле число x, залежно від останніх 2 біт x, виконайте наступне:

x & 3 == 0: 0
x & 3 == 1: x + x
x & 3 == 2: x * x
x & 3 == 3: x ^ x (exponentiation)

Введення-виведення

Single Integer -> Single Integer  

Вихідний новий рядок дозволений у висновку. Жоден інший пробіл не дозволений.

Тестові шафи

input       output
    1            2
    2            4
    3           27
    4            0
    5           10
    6           36
    7       823543
    8            0
    9           18
   10          100
   11 285311670611
   12            0

Це завдання з , тому найкоротший код виграє!


8
Якщо не 0випадок бути x + 2, бачачи, як інші x * 2, x ^ 2і x ^^ 2(тетраци)? : P
ETHproductions

Який найбільший результат, який ми повинні підтримувати (щодо x ^ x)? 32-розрядних вже недостатньо для тестового випадку 11, а 64-розрядних недостатньо для тестового випадку 19.
Кевін Круїссен

@KevinCruijssen Я скажу, що вам належить обробляти лише випадки, коли введення та вихід є в межах вашої мови, доки ваша програма теоретично працюватиме з нескінченним розміром числа.
HyperNeutrino

@HyperNeutrino Гаразд, у такому випадку я виправив свій (Java 7) код (на +72 байти .. xD)
Кевін Круїссен

Відповіді:


13

Желе , 8 байт

ị“+×*_”v

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

Як це працює

По-перше, зауважте, що x&3еквівалентно x%4, де %знаходиться модуль. Потім, оскільки Jelly використовує модульну індексацію ( a[n] == a[n+len(a)]), нам навіть не потрібно з цим боротися.

Потім:

  • Якщо x%4==0, повернути x_x(віднімання) (для консистенції);
  • Якщо x%4==1, поверніть x+x;
  • Якщо x%4==2, повернути x×x(множення);
  • Якщо x%4==3, повернення x*x(експоненція)

Зауважте, що Jelly використовує 1-індексацію, тому віднімання "_"переміщується до кінця.

ị“+×*_”v  example input: 10
ị“+×*_”   index 10 of the string “+×*_”, which gives "×"
       v  evaluate the above as a Jelly expression,
          with 10 as the argument, meaning "10×" is the
          expression evaluated. The dyad "×" takes the
          second argument from the only argument, effectively
          performing the function to itself.

2
@andrybak AFAIK Jelly має власне кодування - дивіться тут , але я знаю, що всі його символи мають 1 байт.
Стефан

"8 байт". Як слід рахувати байти? Ця відповідь складається з восьми символів, але принаймні у кодуванні коду stackexchange, що обслуговує цю сторінку, вона займає 15 байт (підраховано за допомогою wc --bytes).
andrybak

Якщо мова інтерпретує її в одному кодуванні, не має сенсу використовувати інше кодування для підрахунку байтів (imo)
Маккензі Макклайн

@andrybak Код, кодований кодуванням, щоб браузер показав його правильно, становить 15 байт. Код у кодуванні, який Jelly розуміє, це 8 байт. Подивіться на github.com/DennisMitchell/jelly/wiki/Code-page якщо ви хочете знати, як це закодовано.
Етоплей


9

CJam , 12 байт

ri__"-+*#"=~

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

Пояснення

ri            e# Read an int from input (call it x).
  __          e# Duplicate x twice.
    "-+*#"    e# Push this string.
          =   e# Get the character from the string at index x (mod 4).
           ~  e# Eval that char, using the two copies of x from before.

Виконує одну з наступних операцій в залежності від xзначення mod 4 (mod 4 еквівалентно AND 3).

0:  -  Subtraction
1:  +  Addition
2:  *  Multiplication
3:  #  Exponentiation


4

Pyth, 8 байт

.v@"0y*^

Перекладач


Так, я перевірив це, і це працює. І ні, vзамість цього я не можу використовувати .v.
Ерік Аутгольфер

Я подумав, що сфера застосування локальна ... Я думав, що .vне можу отримати доступ Q... Мабуть, я перевершив перевагу в Pyth. +1 для вас.
Лина монашка

@LeakyNun Ні, це vне локальне значення, а .vпросто вираження.
Ерік Аутгольфер

У мене є чому навчитися ...
Leaky Nun

3
Це прекрасно! Це абсолютно дивовижно! Я не мав уявлення, що це навіть можливо. Для стильових точок, "0y*^може бути "-+*^.
isaacg





2

C, 63 або 62 байти

#include<math.h>
f(x){return(int[]){0,x+x,x*x,pow(x,x)}[x&3];}

-1 байт, якщо макроси дозволені, припускаючи, що xце не такий вираз 3+5(оскільки це зіпсує пріоритет):

#include<math.h>
#define f(x)(int[]){0,x+x,x*x,pow(x,x)}[x&3]

@ceilingcat Правильно, забув про це.
Тім Час

не збирається на MSVS2015; Інтеллісенс сказав, що сказав cast to incomplete array type "int[]" is not allowedКомпілерerror C4576: a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax ; ТАКОЖ! де int f (int x)? код насправді принаймні на 8 байт довше; також це дуже повільно і неефективно, оскільки він оцінює Everytning - не повторюй це IRL)

@ xakepp35 Що? 1) він повинен скласти в вигляді C компілятор. Більшість (читайте: майже всі, крім MSVC) компіляторів C підтримують цей (int[])синтаксис для цієї ситуації. 2) f(x)ідеально законний C89. Я не вказав стандарт. 3) Мова йде про розмір коду, а не про ефективність. І 4) Якщо ви збираєтесь опікуватися, принаймні використовуйте справжній компілятор та / або перевіряйте свої факти.
Тім Час

@Tim Čas Ах, так, дуже шкода! Я намагався компілювати його як код C ++. Це я винен) Він чудово компілює та працює!

2

Java 7, 75 байт

long c(int n){int x=n%4;return x<1?0:x<2?n+n:x<3?n*n:(long)Math.pow(n,n);}

Незважаючи на те, що він дійсний за правилами, longє 64-розрядним, тому він не відповідає для випадків тесту експоненціації 19^19вище та вище. Щоб вирішити, що ми можемо використовувати BigDecimalпідхід:

148 146 байт

import java.math.*;BigDecimal c(int n){int x=n%4;BigDecimal m=new BigDecimal(n);return x<1?m.subtract(m):x<2?m.add(m):x<3?m.multiply(m):m.pow(n);}

Пояснення (підходу BigDecimal):

import java.math.*;                // Import required for BigDecimal
BigDecimal c(int n){               // Method with integer parameter and BigDecimal return-type
  int x=n%4;                       //  Input modulo-4
  BigDecimal m=new BigDecimal(n);  //  Convert input integer to BigDecimal
  return x<1?                      //  If the input mod-4 is 0:
    m.subtract(m)                  //   Return input - input (shorter than BigDecimal.ZERO)
   :x<2?                           //  Else if the input mod-4 is 1:
    m.add(m)                       //   Return input + input
   :x<3?                           //  Else if the input mod-4 is 2:
    m.multiply(m)                  //   Return input * input
   :                               //  Else:
    m.pow(n);                      //   Return input ^ input
}                                  // End of method

Код тесту:

Спробуйте тут.

import java.math.*;
class M{
  static BigDecimal c(int n){int x=n%4;BigDecimal m=new BigDecimal(n);return x<1?m.subtract(m):x<2?m.add(m):x<3?m.multiply(m):m.pow(n);}

  public static void main(String[] a){
    for (int i = 1; i <= 25; i++) {
      System.out.print(c(i) + "; ");
    }
  }
}

Вихід:

2; 4; 27; 0; 10; 36; 823543; 0; 18; 100; 285311670611; 0; 26; 196; 437893890380859375; 0; 34; 324; 1978419655660313589123979; 0; 42; 484; 20880467999847912034355032910567; 0; 50; 

Вам не потрібно виправляти програму таким чином: P Стара відповідь спрацювала, якби числа мали нескінченний розмір; перша програма була б дійсною за моїми специфікаціями. : P
HyperNeutrino

@HyperNeutrino Тоді я вказую, що у відповіді .. Ну добре, Java все одно не виграє жодних проблем із кодом-гольфом. ;)
Кевін Круїссен

1
Так, я б уточнив. І так, це Java, це не перемагає. : D
HyperNeutrino

2
" І так, це Java, це не виграє.: D " Я звик до цього. : P Навіть моя найкоротша відповідь на Java з 8 байтів - це шлях довгий порівняно з відповідями на гольф. xD Хоча це був перший раз, коли я побив відповідь Python моєю відповіддю на Java, яка повинна розраховувати за те, що я здогадуюсь. ;)
Кевін Круїссен

2

x86 Assembler, синтаксис Intel, 192 байти

.data
f dw @q,@w,@e,@r
.code
mov ecx, eax
and ecx, 3
mov edx,dword ptr f[ecx*4]
call [edx]
ret
q:
xor eax,eax
ret
w:
add eax,eax
ret
e:
mul eax,eax
ret
r:
mov ecx,eax
t:
mul eax,eax
loop t
ret

Приклад прикидається найшвидшою робочою швидкістю. Is - це програма або програмна частина, яка використовує конвенцію про швидкий виклик. Він передбачає вхідну зміннуx в регістрі eax, а результат повертає також уeax . Основна ідея - це уникати використання умовних стрибків, як у деяких прикладах тут. Крім того, це не для того, щоб оцінювати все (як у прикладі C з масивами), а використовувати масив покажчиків на функтони та робити швидші безумовні стрибки (jmp / call) як оптимізований аналог "переключення мови С () - випадок ..". Цей прийом може бути також корисним у різних finita automata - як емулятори процесорів, виконавці тощо.

Вгору: для x64 використовуйте "r" у назвах регістрів, а не "e" (наприклад, raxзамість eax, rcxа не ecx). Розмір не буде змінено, і він використовуватиме 64-бітні непідписані слова.


Ласкаво просимо до PPCG! Мета цього завдання - зробити ваш код якомога коротшим. У цьому випадку ваш код можна легко скоротити, комбінуючи всі ці декларації функцій. Ви також можете видалити пробіл.
HyperNeutrino

@HyperNeutrino asm - це якось "довга" мова :), тому я не маю уявлення про те, як зробити це коротшим. будь-які приклади-поради?

Ех, вибачте, я, мабуть, скопіював свій коментар до вашої відповіді на С у цей пост. Я не знаю, як програмувати в ASM, але ви могли б потенційно видалити пробіл?
HyperNeutrino

@HyperNeutrino, вибачте ... але, здається, ні) це має бути найдовший код серед інших, я можу просто обрізати windows crlf у форматі Linux, так що 209-> 192 байт, зміни не видно)

Ау. Це дуже погано. Але приємне подання незалежно! :)
HyperNeutrino

2

C #, 39 байт

x=>new[]{0,2,x,Math.Pow(x,x-1)}[x&3]*x;

Пояснення

Зауважте, що:

(xx, x + x, x * x, x ^ x) == (0, 2, x, x ^ (x-1)) * x

Рішення створює масив, індексує його, а потім множує результат на x:

x => new[] { 0, 2, x, Math.Pow(x,x-1) }[x&3] * x;

Альтернативні версії:

x=>new[]{0,x+x,x*x,Math.Pow(x,x)}[x%4];

(39B, все множення, виконане в масиві, x%4замінює x&3)

x=>x%4<2?x%2*2*x:Math.Pow(x,x%4<3?2:x);

(39B, те саме, що відповідь @ MetaColon, але x%2*2*xзамінює x*x%4<1?0:2)





1

Оазис , 25 байт

mn4%3Q*nkn4%2Q*nxn4%1Q*++

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

Як це працює

Зверніть увагу, що x&3еквівалентно x%4, де %знаходиться модуль.

mn4%3Q*nkn4%2Q*nxn4%1Q*++  input is n
mn4%3Q*                    (n**n)*((n%4)==3)
       nkn4%2Q*            (n**2)*((n%4)==2)
               nxn4%1Q*    (n*2)*((n%4)==1)
                       +   add the above two
                        +  add the above two

Oasis - мова на основі стека, де кожен символ є командою.



1

C #, 42 байти

x=>x%4<2?x*x%4<1?0:2:Math.Pow(x,x%4<3?2:x)

Насправді це звичайний C #, але оскільки ви не можете запустити його як цілу програму, і вам доведеться вводити її в інтерактивну, я думаю, ви можете назвати це C # interactive .

Пояснення :

x => (x % 4) < 2     //If the bits are smaller than 2 (1 or 0)
? x *           //multiply x with
    (x % 4) < 1 //if the bits are 0
    ? 0         //0 (results in 0)
    : 2         //or else with 2 (results in 2*x or x+x)
: Math.Pow(x,   //otherwise power x by
    (x % 4) < 3 //if the bits are 2
    ? 2         //2 (results in x^2 or x*x)
    : x);       //or else x (results in x^x)

Я не можу сказати, що це найкоротший варіант, будь-які пропозиції вдячні.


Я не думаю, що це справедливо. Як правило, ви повинні подати програму чи функцію . Фрагменти заборонено за замовчуванням.
Кіос

@Cyoce Це програма. Вам просто потрібно запустити його через інтерактив, який буде інтерпретувати програму.
MetaColon

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

@Cyoce У виклику, який він сказав, буде визначена змінна x.
MetaColon

Це не те, що це означає. «Дано ціле позитивне число x» означає , що ви в даний час дані x з допомогою стандартного методу введення (тобто, функції або програми).
Кіос




1

C, 115 байт

#include<math.h>
#define D(K,L)K(x){return L;}
D(q,0)D(w,x+x)D(e,x*x)D(r,pow(x,x))(*g[])()={q,w,e,r};D(f,g[x%4](x))

Приклад - функція int f(int x)

Він претендує на найшвидшу робочу швидкість, оскільки утримує процесор від використання умовних стрибків. І це лише правильний спосіб оптимізації швидкості для цього завдання. Крім того, він намагається не оцінювати все, як у прикладі масиву Creturn(int[]){0,x+x,x*x,pow(x,x)}[x%4]; Але розумно використовувати масив покажчиків на функтони, щоб зробити набагато швидші беззастережні стрибки (jmp / call) із значно швидшою арифметикою адреси, як оптимізовану версію " switch () - справа .. ". Ця методика також може бути корисною для декількох типів автоматичних фінітів - таких як емулятори процесора, виконавці, аналізатори командного потоку тощо - там, де питання швидкості та код схожий switch(x%4) case(0):... case(1):... є непридатним, оскільки він дає кілька інструкцій cmp / jnz; і це дорогі операції для процесора

Найпростіша та найкоротша програма тестування (за умовчанням) для цього випадку буде такою:

D(main,f(x))

Це додасть всього 12 байт корисного навантаження і загальний наш розмір складе 127 байт;

Але вам краще сказати лінкеру використовувати fфункцію в якості точки входу, а не якmain . Ось так, якщо ми прагнемо отримати якнайшвидший робочий двійковий код для цього завдання з найкоротшого коду ;-) Це трапляється тому, що бібліотека C додає додатковий код init / shutdown перед викликом вашої основної () функції.

Код складається на MSVS Community 2015 без жодних хитрощів і проблем і дає правильні результати. Я не перевіряв його на gcc, але впевнений, що він буде добре працювати.


1
Ласкаво просимо до PPCG! Мета цього завдання - зробити ваш код якомога коротшим. У цьому випадку ваш код можна легко скоротити, комбінуючи всі ці декларації функцій. Ви також можете видалити пробіл.
HyperNeutrino

Мені подобається ідея використання покажчиків на функції
RosLuP

@RosLuP, але це майже вдвічі довше, ніж ваша версія 60 байт. але він працює набагато швидше, варто його розміру.

@Hyper Neutrino Гаразд. Я її більше стиснув. Здається, це остаточна версія! Немає помилок, усі тести пройшли 8-)

@ xakepp35 Ви міряли ваш швидше, ніж мій?
RosLuP

1

R, 47 42 байти

x=scan();c(`-`,`+`,`*`,`^`)[[x%%4+1]](x,x)

Застосовує функцію -, +, *або ^на основі модуля xдо xі x.

- - єдина (дещо) розумна річ, оскільки x-x завжди 0.

R, 33 байти

pryr::f(c(0,2*x,x^2,x^x)[x%%4+1])

Той самий метод, який використовують інші люди. Хоч він і коротший, мені це не подобається майже так.


0

Pyth , 12 байт

.vjd,+@"-+*^

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

Як це працює

По-перше, зауважте, що x&3еквівалентно x%4, де %знаходиться модуль. Потім, оскільки Pyth використовує модульну індексацію (a[n] == a[n+len(a)] ), нам навіть не потрібно з цим боротися.

Потім:

  • Якщо x%4==0, повернітьсяx-x (для консистенції);
  • Якщо x%4==1, повернітьсяx+x;
  • Якщо x%4==2, повернітьсяx*x;
  • Якщо x%4==3, поверніться x^x.

.vjd,+@"-+*^  example input: 10
      @"-+*^  "-+*^"[10], which is "*"
     +        "*10"
    ,         ["*10","10"]
  jd          "*10 10"
.v            evaluate as Pyth expression
              (Pyth uses Polish notation)

Більше про польські позначення: Вікіпедія (дуже погано, якщо ви перебуваєте в Туреччині).


Так? Це мені здається занадто багато. Детальну інформацію див. У моїй відповіді.
Ерік Аутгольфер

0

Japt , 13 байт

Ov"^+*p"gU +U

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

Для цього використовується той самий метод, що й інші відповіді eval, за винятком того, що програма -Uпросто заперечує U, тому ми використовуємо ^(побіжно XOR).


0

Vim, 50 байт

y$o^R"A-+*^^V^[0^R"lx0"_Dp^[0D@"kJ0"ad$:r!echo ^R"^R0|bc^<Enter>

Тут, ^Vявляє собою Ctrl+V, ^Rпредставляє Ctrl-Rі ^[представляєesc ключ

Працює спочатку нарощуючи вираз, а потім відпускаючи bc оцінити його. Очікує введення першого рядка в іншому порожньому буфері.

Пояснення:

y$o^R"                                                          Copies the input into register " and pastes it on the second line
      A-+*^^V^[0^R"lx0"_Dp                                      Enters that text after the input on the second line
                          ^[0D@"                                Executes the second line as a Vim command.
                                                                For example, if the input is 12, the second line would be 12A-+*^^[012lx0"_Dp, which means:
                                                                  12A-+*^^[           Insert the text -+*^ 12 times
                                                                           012lx0"_Dp Go 12 chars to the right and remove everything except for that.
                                                                If effect, this basically just selects the appropriate operation.
                                kJ0"ad$                         Put the operator after the number, cut it into register a
                                       :r!                      Execute the following shell command and put the result into the buffer:
                                          echo ^R"^R0|bc<Enter> The shell command "echo [contents of register a][contents of registers 0]|bc. As said above, register a contains the input and the operator, and register 0 contains the input. The <enter> then executes this command.

Коли я набираю текст, ^Vвін просто вставляє те, що є у своєму буфері обміну, а не номер ...
Leaky Nun,

1
Спробуйте в Інтернеті! Також ви можете зробити Dзамістьd$
DJMcMayhem

0

Pyth, 9 байт

@[0yQ*QQ^

Тестовий набір

Тут нічого фантазійного не відбувається, просто обчисліть чотири значення та виберіть одне з модульним індексуванням.

@[0yQ*QQ^
@[0yQ*QQ^QQ)Q    Implicit variable introduction
@           Q    Modularly index into the following list
 [0        )     0
   yQ            Q*2
     *QQ         Q*Q
        ^QQ      Q^Q

0

Пакетна, 135 байт

@set/an=%1*2^&6
@goto %n%
:6
@set n=1
@for /l %%i in (1,1,%1)do @set/an*=%1
@goto 0
:4
@set n=%1
:2
@set/an*=%1
:0
@echo %n%

Я сподівався створити експоненцію шляхом створення та оцінки рядка форми [0+...+0, 2+...+2, x+...+x, x*...*x]залежно від двох останніх бітів, xале, на жаль, код для вибору операції зайняв занадто багато часу, щоб виразити, тому що я не міг використовувати *як forпараметр, але я був принаймні, в змозі використати якусь хитру осінь, щоб відібрати деякі байти.


0

Сітківка , 87 байт

.+
$*1;$&$*
;((1111)*)(1?)$
;$3$3
1(?=1.*;((1111)*111)$)
$1;
+`\G1(?=.*;(1*))|;1*$
$1
1

Спробуйте в Інтернеті! (Посилання включає тестовий набір.)

Пояснення: Перші два рядки перетворюють вхід в одинаковий і дублюють його (так у нас зараз x;x). Наступні два рядки шукати x&3або 0або 1і зміни x;xв x;0або x;2належним чином . Наступні два рядки пошуку x&3==3і зміни x;xв x;x;x;...;x;1;x( x xз). Це означає , що ми маємо або x;0, x;2, x;x, або x;...;xі залишається помножити все разом і перетворити назад у десятковій системі . (Код множення базується на такому у вікі Retina, але змінено для обробки множення на нуль.)

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