让我们做一些位置运算!


22

维基百科文章

位置算术(拉丁算术,localis)是加法(非位置)二进制数字系统,约翰·纳皮尔在其《犹太论》(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 = 1 + 1 + 2 + 2 = 6(以10为底)

注意 aabb可以bc通过将一个字母的任意两个实例替换为一个较高的字母来简化为。

加成

您只需将两个数字连接起来并简化。

acd+ bde= acdbde= abcdde= acebe= abcf=39以10为底

减法

只需删除在减法的两个部分中均出现的所有数字。可能需要扩展(转换baa

abde- ad=以be18为底的18

乘法

这有点难。

假设我们想将acd(13)乘以def(56)。首先,您acd垂直排列:

a
c
d

然后def在第一个之后添加a

a def
c
d

现在,c在字母表中比a落后2个位置,因此我们在字母表中添加2个位置def以使fgh。那被添加到第二行。

a def
c fgh
d

最后,d在字母表中比c落后1个位置,因此我们在字母表中加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是字母表中的第二个字母,因此我们需要移动de1个字母,所以它变为ef

然后

ef+fg

输出:

eh

这不是挑战的一部分,因为它可能变得非常复杂。

您的实际挑战

您的程序或函数必须以如下所示的字符串形式输入输入:

a + b

并且您必须输出:

ab

当然,你的程序或功能必须支持与任何运营商的任意长度(高达语言的字符串或输入限制)的数量+-*。其他示例:

输入:

ab + bd

输出:

acd

输入:

d - ab

输出:

ac

输入:

ab * cd

输出:

cf

笔记:

  • 输出中字母的顺序无关紧要,但是您始终可以假定输入中数字字母的顺序将递增(在z之前是a)。
  • 您可以使用尾随换行符作为输入,并使用尾随换行符作为输出。
  • 你可能接受输入的列表ab*bdab * bd
  • 使用英文字母(abcdefghijklmnopqrstuvwxyz
  • 您的输出必须简化(aa不允许,b必填)
  • 输入将被简化(b+ c,不是aa+ bbaa+ 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在这里使用英文字母进行编辑。
programmer5000

@ programmer5000还在,bc*de==efgh但是efgh240不是144
菲利普·纳迪巴蒂斯塔

1
bc*de应该是eh
Felipe Nardi Batista

@Dada每个输入只有一个运算符。
程序员

Answers:


3

果冻26 25 字节

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

在OP允许的情况下,在输入字符串中使用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

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个字符?令人惊讶!
程序员

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

1
@ programmer5000是的。我怀疑会有很多答案。(当然Mathematica除外,它可能具有内置功能。^^)
Arnauld

您的评论似乎缺少链接。有什么内建的工具吗?
程序员

@ programmer5000(实际上,它缺少一个词。)
Arnauld

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将连续的相同字母折叠成字母表中的下一个字母。


唯一不能转换为十进制的答案!不错的工作!
programmer5000

1
@ programmer5000 2个答案中,我不会给人留下深刻的印象!
Dada's

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个字符,原因如下:1.由于需要很多功能,每个功能的开销都可以用一些预处理程序规则削减。2.现代linux禁止在堆栈上执行,因此mprotect()调用可禁用此牺牲的34个字节。3. XCHG调用非常次优,另外花费了30个字节。如果不是这些事情,x86组合将赢得大约10-20个字节。

通过改进g中的islower()调用,还将两个字节都砍掉了2个字节。


我真的无法说出它与代码大小方面的经典方法相比,但我真的很喜欢您的解决方案。+1
Arnauld

5

GNU sed + coreutils,329个字节

是的,我不知道是什么原因,但是至少我现在知道sed脚本要好一些。请注意,此解决方案需要GNU sed的e扩展程序,该扩展程序运行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

sed代码+1,欢迎使用PPCG!不使用纯GNU sed(或任何其他纯语言)求解时,此处的约定是在标题中添加使用的系统命令,例如“ GNU sed + coreutils”,即使您在描述中提到了调用shell命令。这样做是为了区别于GNU sed答案,尤其是在排行榜挑战中。
seshoumara

另外,除了每次都需要标志“ f”外,任何其他标志都必须计为1个字节。所以您的分数是329。您可能需要在说明中提及它。为了完成,您可能会考虑添加一个到在线sed解释器的链接,例如TIO
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 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

在线尝试!


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))
Tutleman

1
哦,还有两个字节可以替换2**(ord(i)-97)1<<ord(i)-97
Tutleman

1
与其他解决方案相比,该解决方案的可读性让我感到惊讶。
Ole Tange'4

谢谢 :)。但我认为这也是因为python是所使用的语言。缩进使字节数增加,但是可读性高。;)
Officialaimm'Apr

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是我能想出做一个最好的方式evaluateAWK。我可能会有点“作弊”,称其为AWK由于执行命令,,但至少该命令也是AWK:)

我确定我缺少某种减少字节数的方法,但是我肯定看不到。

用法是相当标准的,例如,将代码放入FILE并执行:

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

请注意,空格不是必需的,任何非op / non [az]字符都将被静默忽略。通过更改循环,可以扩展为使用大于“ abcdefghijklmnopqrstuvwxyz”的数字。要进行除法,只需将/字符添加到操作字符串中即可:)。另外,如果,将打印空白行result <= 0

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.