Давайте зробимо деяку арифметику локації!


22

Зі статті Вікіпедії :

Арифметична локація (лат. Arithmeticæ localis) - це додаткова (не позиційна) двійкова система числення, яку Джон Нап'є досліджував як техніку обчислень у своєму трактаті «Рабдологія» (1617), як символічно, так і на шаховій дошці.

Що?

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

Бінарні позначення ще не були стандартизовані, тому Нап'є використовував те, що він називав цифрами місцеположення, для позначення двійкових чисел. Система Napier використовує позначення знакових знаків для представлення чисел; він використовує послідовні літери з англійського алфавіту для подання послідовних сил двох: a = 2 ^ 0 = 1, b = 2 ^ 1 = 2, c = 2 ^ 2 = 4, d = 2 ^ 3 = 8, e = 2 ^ 4 = 16 тощо.

Приклад

ab = 1 + 2 = 3 в основі 10

aabb = 1 + 1 + 2 + 2 = 6 в основі 10

Зауважте, що aabbйого можна скоротити bc, замінивши будь-які два екземпляри листа на більш високий.

Доповнення

Ви просто з'єднаєте два числа і спростіть.

acd+ bde= acdbde= abcdde= acebe= abcf= 39в базі 10

Віднімання

Просто видаліть усі цифри, які однаково відображаються в обох частинах віднімання. Розширення (перетворення bна aa) може знадобитися

abde- ad= be= 18 в основі 10

Множення

Це трохи складніше.

Скажімо, ми хочемо помножити acd(13) на def(56). Спочатку розташуйте acdвертикально:

a
c
d

Потім ви додаєте defпісля першого a:

a def
c
d

Тепер c є на 2 позиції пізніше в алфавіті, ніж a, тому ми додаємо 2 позиції в алфавіті, defщоб зробити fgh. Це додано до другого ряду.

a def
c fgh
d

Нарешті, d на 1 позицію в алфавіті пізніше c, тому ми додаємо 1 позицію в алфавіті fghдля створення ghi. Це додано до третього ряду.

a def
c fgh
d ghi

Тоді ви берете суму права: def+ fgh+ ghi= deffgghhi= deggghhi= deghhhi= deghii= deghj(728)

Ще один приклад множення

Вхід:

bc * de

Спочатку:

b
c

Потім

b ef
c 

Потім

b ef
c fg

Зауважте, що ми записали efв першому рядку. Це тому, що bcпочинається з bі bє другою літерою в алфавіті, тому нам потрібно зрушити deна 1 букву, так і стає ef.

Потім

ef+fg

Вихід:

eh

Відділ

Це не є частиною цього виклику, оскільки воно може стати дуже складним.

Ваш справжній виклик

Ваша програма чи функція повинні сприймати дані як рядок, який виглядає приблизно так:

a + b

І ви повинні вивести:

ab

Звичайно, ваша програма або функція повинна підтримувати число довільної довжини (до рядка або вхідного межі вашої мови) з будь-яким з операторів +, -або *. Ще кілька прикладів:

Вхід:

ab + bd

Вихід:

acd

Вхід:

d - ab

Вихід:

ac

Вхід:

ab * cd

Вихід:

cf

Примітки:

  • Порядок букв на виході не має значення, але ви завжди можете припустити, що порядок букв у цифрах на вході буде зростати (a до z).
  • Ви можете взяти вхід із зворотним новим рядком та вихід із заднім рядком.
  • Ви можете НЕ приймати вхідний сигнал у вигляді списку ab, *і bdдля ab * bd.
  • Використовується англійський алфавіт ( abcdefghijklmnopqrstuvwxyz)
  • Ваш вихід повинен бути спрощений ( aaне дозволено, bпотрібно)
  • Введення буде спрощено ( b+ c, не aa+ bbабо aa+ aaaa)
  • Вам може знадобитися простір перед і оператор ( +, -або *), або може знадобитися не бути жодного.
  • Буде лише один оператор на вхід.
  • Ви можете припустити, що вихід і вхід ніколи не перевищуватимуть 2 ^ 27-1 ( abcdefghijklmnopqrstuvwxyz)
  • Це , тому найкоротша відповідь у байтах виграє!

2
d is 2 positions later in the alphabet than cце Райт? чи не повинно бути 1? That is added to the second row.в тому ж реченні, чи не має бути third?
Феліпе Нарді Батіста

1
@FelipeNardiBatista тут використовується англійський алфавіт, редагуючи це.
програміст5000

@ programmer5000 все ще, bc*de==efghале efghце 240не так144
Феліпе Нарді Батіста

1
bc*deмає бутиeh
Феліпе Нарді Батіста

@Dada буде лише один оператор на вхід.
програміст5000

Відповіді:


3

Желе , 26 25 байт

i@€Øað’2*S;ḟ.Ḣ
ḲÇ€VBṚTịØa

Використовує операторів Jelly ( ×а не *і _не -) у вхідному рядку, як це дозволено ОП .

(Потрібні пробіли навколо операторів)

Спробуйте в Інтернеті! або побачити тестовий набір

Як?

i@€Øað’2*S;ḟ.Ḣ - Link 1, transform from input sub-string to value or operator: sub-string
i@€            - 1st index of, for €ach (or 0 if not found) [reversed @rguments] in:
   Øa          -      lowercase alphabet (i.e. a->1, b->2, ..., non-alpha->0)
     ð         - dyadic chain separation i.e. f(result above, substring):
      ’        - decrement (i.e a->0, b->1, ..., non-alpha->-1)
       2*      - 2 raised to that power
         S     - sum
          ;    - concatenate with the substring
           ḟ   - filter out:
            .  -     0.5 (for an operator substring the evaluated 0.5 is removed)
             Ḣ - head (i.e. the evaluation for a location, and the operator otherwise)

ḲÇ€VBṚTịØa - Main link: string                        e.g. 'ab × cd'
Ḳ          - split on spaces                               [['a','b'],['×'],['c','d']]
 Ç€        - last link (1) as a monadic function for €ach  [3,'×',12]
   V       - evaluate as Jelly code                        36
    B      - convert to binary                             [1,0,0,1,0,0]
     Ṛ     - reverse                                       [0,0,1,0,0,1]
      T    - truthy indexes                                [3,6]
       ị   - index into:
        Øa -     lowercase alphabet                        ['c','f'] (i.e. "cf", which is implicitly printed when run as a full program)

7

Математика, 168 байт

FixedPoint[StringReplace[x_~~x_:>FromCharacterCode[c@x+1]],Table["a",ToExpression@StringReplace[#,x:LetterCharacter..:>ToString@Tr[2^((c=ToCharacterCode)@x-97)]]]<>""]&

Моє початкове рішення (до того, як публікація була відредагована, щоб уточнити, що вихід повинен бути спрощений) був на 64байт коротшим:

Table["a",ToExpression@StringReplace[#,x:LetterCharacter..:>ToString@Tr[2^(ToCharacterCode@x-97)]]]<>""

Це просто змінило це рішення для роботи. Напевно, коротше реально використовувати методи, описані в виклику, але я все-таки хотів це вирішити.

Пояснення:

Замінює кожну послідовність літер відповідним цілим числом на арифметичний код символів, потім перетворює отриманий рядок у вираз (який автоматично спроститься до цілого числа), потім виробляє рядок aсимволів довжиною, рівним цьому цілому, і, нарешті, замінює сусідні ідентичні символів із наступним кодом символів, поки не буде досягнуто фіксованої точки.


2
О, немає 1-char вбудований? Дивовижні!
програміст5000

7

JavaScript (ES6), 136 134 133 байт

Збережено 1 байт завдяки Луці

s=>[...a='abcdefghijklmnopqrstuvwxyz'].filter((c,i)=>eval(s.replace(/\w+/g,s=>[...s].reduce((p,c)=>p|1<<a.search(c),0)))&1<<i).join``

Тестові кейси


Чудово зроблено! Ти мене побив ...
програміст5000

Чи перетворюється це в десяткові та зворотні? Виявляється так.
програміст5000

1
@ programmer5000 Так. Я підозрюю, що багато відповідей будуть. (За винятком курсу Mathematica, який, мабуть, має вбудований для нього. ^^)
Арнольд

Схоже, у вашому коментарі не було посилання. Що має вбудований фот?
програміст5000

@ programmer5000 (Насправді, у ньому не було слова.)
Арнольд

5

Perl 5 , 95 байт

94 байти коду + -pпрапор.

s/\w/a x 2**(-97+ord$&)/ge;s/(.*)-\1|\+//;/\*/&&($_=$`x length$');1while s/(.)\1/chr 1+ord$1/e

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

Три кроки тут:
- s/\w/a x 2**(-97+ord$&)/ge;перетворює вхід у рядок aлише.
- s/(.*)-\1|+//;/*/&&($_=$`x length$')виконає оператор (це дуже просто для рядків a): +це конкатенація, -означає видалення з першої частини стільки, aскільки їх у другій частині, і *означає дублювання першої частини стільки разів, скільки є aу другій. частина.
- 1while s/(.)\1/chr 1+ord$1/eскладе послідовні ті самі літери на наступну букву в алфавіті.


Єдина відповідь, яка не перетворюється на десяткову! Хороша робота!
програміст5000

1
@ programmer5000 З 2 відповідей я б не назвав це вражаючим!
Дада

5

05AB1E , 29 байт

ð¡À¬U¦v0yvAyko+}}X.VbRvyiANèJ

Спробуйте в Інтернеті! або як тестовий набір

Пояснення

ð¡                             # split input on string
  À                            # rotate left
   ¬U¦                         # get the operator, store it in X and remove it from list
      v                        # for each side of the equation
       0                       # push 0 as an accumulator
        yv                     # for each letter in each side of the equation
          Ayk                  # get its index in the alphabet
             o                 # raise 2 to this power
              +                # add to the accumulator
               }}              # end loops
                 X.V           # apply the operator to the 2 numbers now on the stack
                    bR         # convert to binary and reverse
                      v        # for each binary digit
                       yi      # if it is true
                         ANè   # get the letter at that index in the alphabet
                            J  # join stack to a single string

5

C & x86 asm, 340 байт

Компілюйте з -00

#define G getchar()
g(){int c,a=0;for(;islower(c=G);)a+=1<<(c-97);return a;}
main(){short o[]={[43]=0x4403,[45]=0x442b,[42]=0x6cf7};
mprotect((long)&&l&~4095,4096,7);
for(;;){int c,b=0,a=g();*(short*)&&l=o[G];G;g();asm("xchg %%eax,%0":"+m"(a));
l:asm("addl %1,%%eax":"=a"(c):"m"(a));
for(;a=c>>b;b++)if(a&=1)putchar(97+b);putchar(10);}}

Пояснення

Оскільки у C цього немає eval(), я використав таблицю інструкцій x86 замість нього. Мені довелося вибирати інструкції, які були однакової довжини (або оббиті носами), і які очікували src та призначення одного типу. Особливе роздратування викликало те, що MUL може записувати тільки до регістрів, а 1-байтові MUL-коди можуть записувати лише в EAX. Крім того, здавалося, що не існує інструкції, яка записує реєстр SUB, яка б віднімалася від пам'яті, а не навпаки, звідси XCHG.

редагувати

Оскільки це було запитано в коментарях, більш традиційний приклад виглядав би так:

#define G getchar()
#define return r
#define int i
g(){i c,a=0;for(;islower(c=G);)a+=1<<(c-97);r a;}
a(i x,i y){r x+y;}s(i x,i y){r x-y;}m(i x,i y){r x*y;}
main(){i(*o[])(i,i)={[43]=a,[45]=s,[42]=m};
for(;;){i c,b,a=g();b=G;G;g();c=o[b](a,g());
for(b=0;a=c>>b;b++)if(a&=1)putchar(97+b);putchar(10);}}

Це насправді трохи коротше, на 301 символів, з кількох причин: 1. Оскільки потрібно багато функцій, накладні витрати кожної можуть бути порушені за допомогою деяких правил препроцесора. 2. Сучасний Linux захищає від виконання на стеку, тому mprotect () вимагає відключити цю жертву 34 байти. 3. Виклик XCHG дуже неоптимальний і коштує ще 30 байт. Якби не ці речі, комбінація x86 виграла б приблизно 10-20 байт.

Також нарізаний 2 байти з обох, покращуючи дзвінок islower () в g.


Я не можу сказати, як це можна порівняти з більш класичним підходом з точки зору розміру коду, але мені дуже подобається ваше рішення. +1
Арнольд

5

GNU sed + coreutils, 329 байт

Так, я поняття не маю, що в мене потрапило, але я, принаймні, знаю, що сценарій седа трохи краще. Зауважте, що для цього рішення потрібне eрозширення GNU sed , яке виконує команду shell.

/\+/{s/\+//
b S}
/-/{:E
/a+-a+/{s/(a*)(a*)-\2/\1/
b S}
s/.*/echo &|tr b-z- A-Y-/
e
s/([A-Z])/\L\1\1/g
b E}
/\*/{h
:M
/^\*/{x
s/[^\n]*//
s/\n//g
b S}
s/(.).*\*(.*)/echo \2|tr a-z \1-za-z/
e
H
g
s/.(.*)/\1/
h
s/\n.*//
b M}
:S
s/^.*$/echo &|grep -o .|sort|tr -d '\n'/
e
:L
s/(.)\1/\u\1/g
/^[a-z]*$/ q
s/.*/echo &|tr A-Z b-za/;e
b L

Я припускаю, що навколо операторів не буде пробілів. З мого терміналу:

$ sed -rf golf.sed <<< a+b
ab
$ sed -rf golf.sed <<< ab+bd
acd
$ sed -rf golf.sed <<< abc+b
ad
$ sed -rf golf.sed <<< d-ab
ca
$ sed -rf golf.sed <<< ab*cd
cf
$ sed -rf golf.sed <<< bc*de
eh
$ sed -rf golf.sed <<< acd*def
deghj

І для тих безпечніших за мене: коментована версія!

#!/bin/sed -rf

/\+/ {
    s/\+//
    b simplify
}

/-/ {
    # expand pattern space; everything will now be 'a's
    :E
    /a+-a+/{
        # Remove doubled 'a's on either side of the dash. For example,
        # for input d-ab, space is now 'aaaa-aaa'; substitute this to 'a'
        s/(a*)(a*)-\2/\1/
        b simplify
    }
    # shift letters that aren't 'a' down and double them
    s/.*/echo &|tr b-z- A-Y-/;e
    s/([A-Z])/\L\1\1/g
    b E
}

/\*/ {
    # Hold space: line 1 is pattern, other lines are output
    h
    :M

    # if space starts with *, we've eaten entire arg0; sum and simplify
    /^\*/ {
        x
        s/[^\n]*//      # remove first line, which is our pattern
        s/\n//g         # remove newlines to add results together
        b simplify
    }

    # convert pattern into shifting command
    s/(.).*\*(.*)/echo \2|tr a-z \1-za-z/

    # execute it, append result to hold space
    e
    H

    # restore pattern, with leading char and all output lines removed
    g
    s/.(.*)/\1/
    h
    s/\n.*//

    b M
}

:simplify
# reorder all letters so all 'a's are before all 'b's are before all 'c's
# are before ... etc    
# See /programming/2373874
s/^.*$/echo &|grep -o .|sort|tr -d '\n'/
e

:L
# Replace repeated characters with themselves upper-cased, then translate
# upper-cased characters to what they should be.
s/(.)\1/\u\1/g
/^[a-z]*$/ q
s/.*/echo &|tr A-Z b-za/;e
b L

+1 для коду sed і ласкаво просимо до PPCG! Конвенція тут, коли не вирішується чистим GNU sed (або будь-якою іншою чистою мовою), полягає в додаванні до заголовку системних команд, наприклад "GNU sed + coreutils", наприклад, навіть якщо ви вказуєте виклик команди оболонки в описі . Це робиться для того, щоб відрізняти, особливо у проблемах з колегіями лідерів, від чистих відповідей GNU sed.
seshoumara

Крім того, крім прапора "f", необхідного кожного разу, будь-який інший прапор повинен рахуватися як 1 байт. Отже ваш рахунок 329. Ви можете згадати це в описі. А для завершення можна подумати про додавання посилання до онлайн-інтерпретатора sed, наприклад TIO .
seshoumara

Щоб не всі говорити і не діяти, ось на 43 байти коротше! версія вашого коду (286 байт, включаючи -r), яку я знайшов, граючи команди. Я впевнений, що це може бути і коротше.
seshoumara

Ах, добре, добре знати! Також приємного гольфу! Яку версію sed ви використовуєте? Ваш працює в TIO, але в GNU sed 4.4 я тільки отримуюsed: file golf.sed line 24: ":" lacks a label
charliegreen

Безіменна мітка - добре відома помилка в GNU sed, яка була виправлена ​​у версії 4.3. Але на PPCG ви можете писати програми для будь-якого варіанту та версії sed, використовуючи помилки як функції, якщо це допомагає в гольфі. Різниці між версіями занадто малі, щоб згадати (4.2 проти 4.4), але варіант (стандартний POSIX sed проти розширеного GNU sed) повинен бути вказаний у заголовку, із зазначенням системних програм, що називаються, якщо такі є.
seshoumara

4

PHP, 168

Вихід По зростанні з використанням eval

[$a,$o,$b]=explode(" ",$argn);function d($s){for(;$i<strlen($s);)$n+=2**(ord($s[$i++])-97);return$n;}for(eval("\$k=d($a)$o d($b);");$i<26;)echo$k&2**$i++?chr(96+$i):"";

PHP, 185 байт

Вихід по зростанню

[$a,$o,$b]=explode(" ",$argn);function d($s){for(;$i<strlen($s);)$n+=2**(ord($s[$i++])-97);return$n;}for(;$i<26;)echo(bc.[mul,add,0,sub][ord($o)-42])(d($a),d($b))&2**$i++?chr(96+$i):"";

Інтернет-версія

Розширено

[$a,$o,$b]=explode(" ",$argn); # part the input into variables
function d($s){ # make decimal value
    for(;$i<strlen($s);)$n+=2**(ord($s[$i++])-97);
    return$n;
}
for(;$i<26;)
echo(bc.[mul,add,0,sub][ord($o)-42])(d($a),d($b))&2**$i++?chr(96+$i):""; # Bitwise Compare and Output

PHP, 201 байт

Виробничий тиск

[$a,$o,$b]=explode(" ",$argn);function d($s){for(;$i<strlen($s);)$n+=2**(ord($s[$i++])-97);return$n;}for($r=(bc.[mul,add,0,sub][ord($o)-42])(d($a),d($b));$r;$r-=2**$l)$t.=chr(97+$l=log($r,2)^0);echo$t;

Інтернет-версія

Розширено

[$a,$o,$b]=explode(" ",$argn); # part the input into variables
function d($s){ # make decimal value
    for(;$i<strlen($s);)$n+=2**(ord($s[$i++])-97);
    return$n;
}
for(
$r=(bc.[mul,add,0,sub][ord($o)-42])(d($a),d($b)) # result of the operation
;$r;
$r-=2**$l) # subtract the letter value 
$t.=chr(97+$l=log($r,2)^0); # find greatest letter
echo$t; # Output

4

Пітон 3 , 176 167 байт

i=lambda a:str(sum(1<<ord(i)-97for i in a))
def f(a):
 a,b,c=a.split();m=eval(i(a)+b+i(c));r=''
 while m:
  t=0
  while m>=2**t*2:t+=1
  r+=chr(97+t);m-=2**t
 return r

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

  • збережено 9 байт: Завдяки tutleman

1
Якщо я не помиляюся, ви можете збрити два байта, замінивши m>=2**(t+1)з m>=2**t*2і п'ять байтів, замінивши a=a.split();m=eval(i(a[0])+a[1]+i(a[2]))що - щось на зразок b,c,d=a.split();m=eval(i(b)+c+i(d)).
Тутлеман

1
О, і ще два байти замінивши 2**(ord(i)-97)на 1<<ord(i)-97.
Тутлеман

1
Я вражений тим, наскільки читабельним є це рішення порівняно з іншими рішеннями.
Оле Танге

Дякую :). Але я думаю, що це також через те, що python використовується мовою. Відступ дозволяє збільшити кількість байтів, хоч і читабельних. ;)
officialaimm

2

PHP, 130

for($d=a;$e=$argn[$i++];)$e!=' '?$d!=b?$$d+=1<<ord($e)-97:$b=$e:++$d;eval("for(;\$j++<27;)echo($a$b$c>>\$j-1)&1?chr(96+\$j):'';");

розширена версія:

for($d=a;$e=$argn[$i++];)       // for each char in the input
  $e!=' '?                      //   if space
    $d!=b?                      //     if not the operation
      $$d+=1<<ord($e)-97:       //       add 2^(char - 'a')
      $b=$e:                    //     else save operation
    ++$d;                       //   else increase "pointer"
eval("for(;\$j++<27;)           // for each bit in the output
        echo($a$b$c>>\$j-1)&1?  //   calulate the result and check the bit
          chr(96+\$j):          //     output corrosponding char
          '';                   //     output nothing
     ");

бігати з php -R <code>.


1

AWK, 201 байт

BEGIN{RS="(.)"}n=index(V="abcdefghijklmnopqrstuvwxyz",RT){s+=2^--n}index("+-*",RT){a=s RT
s=0}END{RS="\n"
"(awk '$0="a s"'<<<1)"|getline v
for(j=26;j--;)if((s=v-2^j)>=0){v=s;c=substr(V,j+1,1)c}print c}

"(awk '$0="a s"'<<<1)"|getline vце найкращий спосіб , яким я міг придумати , щоб зробити evaluateпо прибуттю AWK. Я, можливо, трохи "обманюю", щоб це просто назвати AWK, оскільки я виконую команду, але принаймні команда також AWK:)

Я впевнений, що мені не вистачає способу зменшити кількість байтів, але я не можу його побачити.

Використання є досить стандартним, наприклад, введіть код FILEі зробіть:

awk -f FILE <<< "bc + ab"

Зауважте, що пробіли не потрібні, і будь-який неоперативний / не [az] символ буде беззвучно ігнорований. Може бути розширений для роботи з числами, що перевищують "abcdefghijklmnopqrstuvwxyz", змінивши цикл. Щоб зробити поділ, просто додайте /символ до рядку операції :). Також буде надруковано порожній рядок, якщо result <= 0.

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