Bazı konum aritmetik yapalım!


22

Gönderen Vikipedi makalesinde :

Konum aritmetiği (Latin arithmeticæ localis), John Napier'in, hem sembolik olarak hem de satranç tahtası benzeri bir ızgara üzerinde, Rabdology (1617) adlı eserinde bir hesaplama tekniği olarak araştırdığı katkı (konumsal olmayan) ikili sayı sistemleridir.

Ne?

Yer sayıları, alfabenin harflerini kullanarak sayı yazmanın bir yoludur.

İkili gösterim henüz standartlaştırılmamıştı, bu yüzden Napier ikili sayıları temsil etmek için konum numaraları denilen şeyi kullandı. Napier sistemi sayıları temsil etmek için işaret-değer gösterimini kullanır; iki harfin birbirini takip eden güçlerini temsil etmek için İngilizce alfabesinden art arda gelen harfleri kullanır: a = 2 ^ 0 = 1, b = 2 ^ 1 = 2, c = 2 ^ 2 = 4, d = 2 ^ 3 = 8, e = 2 ^ 4 = 16 vb.

Bir örnek

ab 10 bazında = 1 + 2 = 3

aabb = 10 + 1 = 1 + 2 + 2 = 6

Not aabbiçin kısaltılabilir bcdaha yüksek tek bir harf herhangi 2 örneklerini değiştirerek.

İlave

Siz sadece iki sayıyı birleştirin ve basitleştirin.

acd+ bde= acdbde= abcdde= acebe= abcf= 3910 bazında

Çıkarma

Çıkarmanın her iki kısmında da eşit şekilde görünen tüm sayıları kaldırmanız yeterli. Genişleyen (dönüştürme biçin aagerekli olabilir)

abde- ad= be10'da 18 =

Çarpma işlemi

Bu biraz daha zor.

Diyelim ki acd(13) ile def(56) çarpmak istiyoruz . Önce acddikey olarak düzenleme yapın :

a
c
d

Sonra ilkinden defsonra eklersiniz a:

a def
c
d

Şimdi, c alfabede a'dan daha 2 konumlu olduğundan def, yapmak için alfabeye 2 konum ekleriz fgh. Bu ikinci satıra eklenir.

a def
c fgh
d

Son olarak, d alfabede c'den 1 konum sonradır, bu yüzden fghyapmak için alfabeye 1 konum ekleriz.ghi . Bu üçüncü satıra eklenir.

a def
c fgh
d ghi

Sonra sağın toplamını alırsınız: def+ fgh+ ghi= deffgghhi= deggghhi=deghhhi = deghii= deghj(728)

Başka bir çarpma örneği

Giriş:

bc * de

İlk:

b
c

Sonra

b ef
c 

Sonra

b ef
c fg

efİlk satırda yazdığımızı not edin . Bunun nedeni alfabenin ikinci harfiyle bcbaşlıyor bve bbu yüzden de1 harfe kaydırmalıyız , yanief .

Sonra

ef+fg

Çıktı:

eh

Bölünme

Bu, bu zorluğun bir parçası değil çünkü çok karmaşık bir hal alabilir.

Gerçek zorlukların

Programınız veya işlevin, şöyle görünen bir dize olarak girdi alması gerekir:

a + b

Ve çıkmalısınız:

ab

Tabii ki, programınız veya işlev operatörlerin herhangi biri (dilinizin dize veya giriş sınırına kadar) istenilen uzunlukta numaralarını desteklemesi gerekir +, -ya da *. Biraz daha örnek:

Giriş:

ab + bd

Çıktı:

acd

Giriş:

d - ab

Çıktı:

ac

Giriş:

ab * cd

Çıktı:

cf

Notlar:

  • Çıktıdaki harflerin sırası önemli değildir, ancak girişteki sayıların içindeki harflerin sırasının artacağını varsayabilirsiniz (bir z'den önce).
  • İzleyen bir yeni satır ile girdi alabilir ve izleyen bir yeni satır ile çıktı alabilirsiniz.
  • Sen olabilir değil listesi gibi girdi almak ab, *ve bdiçin ab * bd.
  • İngilizce alfabe kullanılır ( abcdefghijklmnopqrstuvwxyz)
  • Çıktınızın basitleştirilmesi gerekir ( aaizin verilmiyor,b gerekli)
  • Giriş basitleştirilecektir ( b+ c, aa+ bbveya aa+ değil aaaa)
  • Sen önce bir boşluk ve operatör (gerektirebilir +, -ya *) veya hiçbiri orada gerektirebilir.
  • Giriş başına sadece bir operatör olacaktır.
  • Çıktı ve girişin hiçbir zaman 2 ^ 27-1 ( abcdefghijklmnopqrstuvwxyz) geçmeyeceğini varsayabilirsiniz.
  • Bu , yani bayt cinsinden en kısa cevap kazanır!

2
d is 2 positions later in the alphabet than cbu wright olmamalı mıydı 1? That is added to the second row.Aynı cümleyle, öyle değil mi third?
Felipe Nardi Batista

1
@FelipeNardiBatista burada kullanılan ingilizce alfabe düzenlenmiştir.
programcı5000

@ programmer5000 hala bc*de==efghama efghbir 240değil144
Felipe Nardi Batista

1
bc*deolmalıeh
Felipe Nardi Batista

@Dada giriş başına sadece bir operatör olacak.
programmer5000

Yanıtlar:


3

Jöle , 26 25 bayt

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

Jelly operatörleri (Kullanımları ×yerine *ve _yerine -olarak giriş dizesi) OP tarafından izin .

(Operatörlerin etrafındaki boşlukları gerektirir)

Çevrimiçi deneyin! veya test odasına bakın

Nasıl?

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

Mathematica, 168 bayt

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

İlk çözümüm (gönderinin basitleştirilmesi gerektiğini açıklığa kavuşturmak için göndermeden önce) 64bayt kısaydı:

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

Bu sadece işe bu çözümü değiştirdi. Mücadelede anlatılan metotları kullanmak aslında daha kısa, ama yine de bunu koymak istedim.

Açıklama:

Her harf sırasını, karakter kodu aritmetiği ile karşılık gelen tamsayı ile değiştirir, sonra elde edilen dizgiyi bir ifadeye dönüştürür (otomatik olarak bir tamsayıya dönüştürür), sonra ao tamsayıya eşit uzunlukta bir karakter dizesi üretir ve son olarak bitişik olarak aynı olur Sabit bir noktaya ulaşılana kadar bir sonraki karakter kodunu içeren karakterler


2
Ah, 1 karakterli dahili yok mu? Şaşırtıcı!
programmer5000

7

JavaScript (ES6), 136 134 133 bayt

Luke sayesinde 1 bayt kaydedildi

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``

Test durumları


Güzel bitti! Beni yendin ...
programmer5000

Bu ondalık ve geri dönüştürür mü? Öyle görünüyor.
programcı5000

1
@ programmer5000 Evet, gerçekten. Pek çok cevabın olacağını sanıyorum. (Tabii ki bunun için yerleşik bir yapıya sahip olan Mathematica hariç. ^^)
Arnauld

Yorumunuzda bir bağlantı eksik görünüyor. İçinde yerleşik olan ne?
programmer5000

@ programmer5000 (Aslında, bir kelime eksikti.)
Arnauld,

5

Perl 5 , 95 bayt

94 bayt kodu + -pbayrak.

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

Çevrimiçi deneyin!

Buradaki üç adım:
- s/\w/a x 2**(-97+ord$&)/ge;girişi ayalnızca bir dizgeye dönüştürür .
- s/(.*)-\1|+//;/*/&&($_=$`x length$')(ipleri üzerine çok basit operatörü çalıştırır a): +birleştirme, olduğu -birçok ilk bölümünden kaldırarak aracı aikinci bölümünde olduğu gibi, ve *olduğu gibi çok kez ilk bölümü çoğaltarak araçlarının aikinci Bölüm.
- 1while s/(.)\1/chr 1+ord$1/eardışık aynı harfleri alfabedeki bir sonraki harfe katlar.


Ondalık dönüşmeyen tek cevap! İyi iş!
programmer5000

1
@ programmer5000 2 cevaptan, bu etkileyici demezdim!
Dada

5

05AB1E , 29 bayt

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

Çevrimiçi deneyin! veya Test paketi olarak

açıklama

ð¡                             # 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 Bayt

-O0 ile derle

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

açıklama

C sahip olmadığından eval() , yerine x86 talimatlarını içeren bir tablo kullandım. Aynı uzunluktaki (veya nops ile dolgulu) ve aynı tipte src ve hedeflenen komutları seçmek zorunda kaldım. Özellikle rahatsızlık, MUL’ın sadece yazmaçlara yazabilmesi ve 1 baytlık MUL opkodlarının yalnızca EAX’e yazabilmesiydi. Ek olarak, XCHG'nin tersi yerine, bellekten çıkarılmış olan kayıt yazma SUB komutu yok gibiydi.

Düzenle

Yorumlarda sorulmasından bu yana, daha geleneksel bir yaklaşım şöyle görünür:

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

Aslında, 301 karakterde, birkaç nedenden ötürü biraz daha kısa: 1. Çok fazla işlev olması gerektiğinden, her birinin ek yükü bazı önişlemci kuralları ile kesilebilir. 2. Modern linux istif üzerinde çalıştırılmaya karşı korur, böylece mprotect () bu kurban edilmiş 34 baytı etkisiz hale getirir. 3. XCHG çağrısı son derece düşüktür ve 30 bayta daha mal olur. Bu şeyler olmasa, x86 combo yaklaşık 10-20 bayt kazanacaktı.

Ayrıca islower () çağrısını g.


Kod boyutu açısından daha klasik bir yaklaşımla nasıl karşılaştırılacağını gerçekten söyleyemem, ama çözümünüzü gerçekten seviyorum. +1
Arnauld,

5

GNU sed + coreutils, 329 bayt

Evet, neyin içine girdiğime dair hiçbir fikrim yok, ama en azından şimdi daha iyi senaryo yazmayı biliyorum. Bu çözümün ebir kabuk komutu çalıştıran GNU sed'in uzantısını gerektirdiğini unutmayın .

/\+/{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

Operatörlerin etrafında boşluk olmayacağını tahmin ediyorum. Terminalimden:

$ 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

Ve benden daha aklı başında olanlar için: yorum yapan versiyon!

#!/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

Sed kodu için +1 ve PPCG'ye hoş geldiniz! Saf GNU sed'de (veya başka bir saf dilde) çözülmediğinde buradaki kural, örneğin "GNU sed + coreutils" gibi kullanılan sistem komutlarını, örneğin bir kabuk komutu çağırmaktan söz etseniz bile . Bu, özellikle lider-kurullarla olan zorluklarda saf GNU sed cevaplarından ayırt etmek için yapılır.
seshoumara

Ayrıca, her zaman gerekli 'f' bayrağı dışında, başka bir bayt 1 bayt olarak sayılmalıdır. Yani puanınız 329. Açıklamasında belirtmek isteyebilirsiniz. Tamamlanması için, TIO gibi çevrimiçi bir tercümana bağlantı eklemeyi düşünebilirsiniz .
seshoumara

Tüm konuşma ve eylem yok olmamak için, burada 43 bayt daha kısa! kodunuzun versiyonunu (-r dahil 286 bayt), komutları golf oynayarak buldum. Eminim daha da kısa olabilir.
seshoumara

Ah, tamam, bilmek güzel! Ayrıca, güzel golf! Gerçi hangi sed sürümünü kullanıyorsunuz? Sizinki TIO'da çalışıyor ama GNU sed 4.4'te sadece alıyorumsed: file golf.sed line 24: ":" lacks a label
charliegreen

İsimsiz etiket, GNU sed'de 4.3 sürümünde düzeltilen iyi bilinen bir hatadır. Ancak PPCG'de, golf oynamaya yardımcı oluyorsa, özellikleri böcek olarak kullanarak, her türlü değişken ve sürüm için programlar yazabilirsiniz. Sürümler arasındaki farklardan bahsetmek için çok küçük (4.2 vs 4.4), ancak varyantın (varsa standart POSIX sed ve genişletilmiş GNU sed) başlığında, eğer varsa, sistem programlarından bahsedilmesi gerekiyor.
seshoumara

4

PHP, 168

Eval kullanımıyla artan çıktı

[$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 Bayt

Artan Çıktı

[$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):"";

Çevrimiçi sürüm

Expanded

[$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 Bayt

Çıktı Düşen

[$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;

Çevrimiçi sürüm

Expanded

[$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

Python 3 , 176 167 bayt

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

Çevrimiçi deneyin!


1
Yanılmıyorsam, siz değiştirerek iki bayt kapalı tıraş edebilirsiniz m>=2**(t+1)ile m>=2**t*2değiştirerek ve beş bayt a=a.split();m=eval(i(a[0])+a[1]+i(a[2]))gibi bir şey ile b,c,d=a.split();m=eval(i(b)+c+i(d)).
Tutleman

1
Oh, ve değiştirerek iki bayt 2**(ord(i)-97)ile 1<<ord(i)-97.
Tutleman

1
Bu çözümün diğer çözümlerle karşılaştırıldığında ne kadar okunabilir olduğunu görünce şaşırdım.
Ole Tange

Teşekkür ederim :). Ama bence kullanılan dilin python olmasından da kaynaklanıyor. Girinti, bayt sayısının artmasına rağmen okunabilir olmasını sağlar. ;)
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):'';");

genişletilmiş sürüm:

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
     ");

koşmak php -R <code> .


1

AWK, 201 bayt

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 Yapabileceğim en iyi yol bu evaluate girişAWK . Ben sadece AWKbir komut yürütüyorum çünkü bu sadece aramak için biraz hile olabilir , ama en azından komut daAWK :)

Bayt sayısını azaltmanın bir yolunu kaçırdığımdan eminim, ama kesinlikle göremiyorum.

Kullanım oldukça standart, örneğin kodu FILE girip şunu yapın:

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

Boşlukların gerekli olmadığına ve op olmayan / [az] olmayan karakterlerin sessizce göz ardı edileceğine dikkat edin. Döngüyü değiştirerek "abcdefghijklmnopqrstuvwxyz" den daha büyük sayılarla çalışmak üzere uzatılabilir. Bölünme yapmak için, /karakterleri işlem dizisine eklemeniz yeterlidir :). Ayrıca, eğer boş bir satır yazdırır result <= 0.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.