位置計算をしましょう!


22

ウィキペディアの記事から:

位置算術(ラテン算術localis)は、加算的(非位置)2進数字システムであり、John Napierが論文Rabdology(1617)の計算手法として、記号的およびチェス盤のようなグリッド上で探索しました。

何?

ロケーション数字は、アルファベットの文字を使用して数字を書く方法です。

バイナリ表記はまだ標準化されていなかったため、Napierはロケーション番号と呼ばれるものを使用してバイナリ数を表しました。Napierのシステムは、符号値表記を使用して数値を表します。英語のアルファベットの連続した文字を使用して、2の累乗を表します。a = 2 ^ 0 = 1、b = 2 ^ 1 = 2、c = 2 ^ 2 = 4、d = 2 ^ 3 = 8、e = 2 ^ 4 = 16など。

ab 基数10で= 1 + 2 = 3

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

文字の任意の2つのインスタンスをより高いインスタンスに置き換えるaabbことで短縮できることに注意してくださいbc

添加

2つの数値を連結して単純化します。

acd+ bde= acdbde= abcdde= acebe= abcf= 3910を底

減算

減算の両方の部分に等しく現れる数字をすべて削除します。エキスパンド(変換baa必要であるかもしれません)

abde- ad= be=基数10の18

乗算

これは少し難しいです。

acd(13)にdef(56)を掛けたいとしましょう。最初にacd垂直に配置します:

a
c
d

次にdef、最初の後に追加しますa

a def
c
d

ここで、cはaよりアルファベットの2桁遅い位置にあるのでdef、makeにアルファベットの2桁を追加しますfgh。それが2行目に追加されます。

a def
c fgh
d

最後に、dはアルファベットのcより1桁遅い位置にあるためfgh、makeにアルファベットの1桁を追加しますghi。それが3行目に追加されます。

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の前)であると常に仮定できます。
  • 入力は末尾の改行で、出力は末尾の改行で取得できます。
  • あなたはありませんのリストとして入力を取るab*bdのためにab * bd
  • 英語のアルファベットが使用されます(abcdefghijklmnopqrstuvwxyz
  • 出力を簡素化する必要があります(aa許可されていません、b必須です)
  • 入力が簡略化されるであろう(b+ cなく、aa+ bbまたはaa+ aaaa
  • あなたは前にスペースとオペレータを(必要な場合があり+-または*)、またはあなたはどれがないように要求することができます。
  • 入力ごとに1つの演算子のみが存在します。
  • 出力と入力が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は英語のアルファベットをここで使用し、それを編集しました。
Programmer5000

@ programmer5000はまだですbc*de==efghが、そうでefghはあり240ません144
フェリペナルディバティスタ


@Dadaでは、入力ごとに演算子は1つだけです。
Programmer5000

回答:


3

ゼリー26 25 バイト

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

ゼリーの事業者(使用×ではなく、*_いうより-、入力文字列内)をOPで許可されています

(演算子の周りにスペースが必要です)

オンラインでお試しください!またはテストスイートを見る

どうやって?

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バイト

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文字の組み込みはありませんか?驚いた!
Programmer5000

7

JavaScript(ES6)、136 134 133バイト

Lukeのおかげで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``

テストケース


よくできました!あなたは私にそれを打ち負かした...
Programmer5000

これは10進数に変換されますか?そう見えます。
Programmer5000

1
@ programmer5000はい、確かに。多くの答えが出てくると思います。(もちろん、おそらく組み込みのMathematicaを除く。^^)
Arnauld

コメントにリンクが欠落しているようです。組み込みのfotには何がありますか?
Programmer5000

@ 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

オンラインでお試しください!

ここでの3つのステップ:
- s/\w/a x 2**(-97+ord$&)/ge;入力を文字列aのみに変換します。
- s/(.*)-\1|+//;/*/&&($_=$`x length$')(の列に非常に単純であるオペレータを実行するa):+連結、ある-多くのように、第1の部分から除去手段a第二部分にあるように、そして*あるよう回数だけ最初の部分を複製手段は、a第二に部。
- 1while s/(.)\1/chr 1+ord$1/e連続する同じ文字をアルファベットの次の文字に折ります。


10進数に変換しない唯一の答えです!良くやった!
Programmer5000

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バイト

-O0でコンパイルします

#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命令の表を使用しました。すべて同じ長さ(またはnopsでパディング)で、同じタイプの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文字で少し短くなります。いくつかの理由があります。2.最新のLinuxはスタックでの実行から保護するため、この犠牲になった34バイトを無効にするmprotect()呼び出し。3. XCHG呼び出しは最適ではなく、さらに30バイトかかります。そうでない場合、x86コンボは約10〜20バイト勝ちます。

また、gのislower()呼び出しを改善することにより、両方から2バイトを切り取りました。


コードサイズの点で、より古典的なアプローチと比較してどうなるかはわかりませんが、あなたのソリューションは本当に気に入っています。+1
アーナルド

5

GNU sed + coreutils、329バイト

ええ、私は何が自分になったのかわかりませんが、少なくとも今はsedスクリプトの方が少し良くなっています。このソリューションにはe、シェルコマンドを実行するGNU sedの拡張機能が必要であることに注意してください。

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

sedコードの+1で、PPCGへようこそ!ここで純粋なGNU sed(または他の純粋な言語)で解決しない場合の規則は、説明でシェルコマンドの呼び出しを言及している場合でも、たとえば「GNU sed + coreutils」などのシステムコマンドを使用するタイトルに追加することです。これは、特にリーダーボードに関する課題において、純粋なGNU sedの回答と区別するために行われます。
seshoumara

また、毎回必要なフラグ「f」を除き、他のフラグは1バイトとしてカウントする必要があります。したがって、あなたのスコアは329です。説明でそれを言及することができます。そして、完成のために、TIOのようなオンラインsedインタープリターへのリンクを追加することを考えるかもしれません。
seshoumara

すべて話せず、何もしないように、ここでは43バイト短くしています!コマンドのゴルフで見つけたコードのバージョン(-rを含む286バイト)。もっと短くできると確信しています。
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

Pythonの3176の 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

オンラインでお試しください!


1
誤解しない限り、で置き換えることm>=2**(t+1)で2バイトを削り取り、のようなものでm>=2**t*2置き換えることa=a.split();m=eval(i(a[0])+a[1]+i(a[2]))で5バイト削ることができますb,c,d=a.split();m=eval(i(b)+c+i(d))
タトルマン

1
ああ、と置き換えることにより、2つの以上のバイト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"

スペースは不要であり、非op / non [az]文字は暗黙的に無視されることに注意してください。ループを変更することにより、「abcdefghijklmnopqrstuvwxyz」より大きい数値で動作するように拡張できます。除算を行うには、/文字を操作文字列に追加するだけです:)。また、の場合は空白行を印刷しますresult <= 0

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.