星期一迷你高尔夫#3:字谜距离


24

星期一迷你高尔夫:每周一发布(希望!)一系列简短的挑战赛。
(对不起,这有点晚。)

我敢肯定,你们大多数人都听说过Levenshtein distance,一种用于计算两个琴弦之间距离的算法。嗯,这个挑战是关于实现我自己的发明*的类似算法,即anagram distance。主要区别在于字符的顺序无关紧要。而是仅测量一个字符串或另一个字符串唯一的字符。

挑战

挑战的目标是编写一个程序或函数,该程序或函数接受两个字符串并返回它们之间的字谜距离。实现此目的的主要方法是使用以下逻辑:

  1. 将两个字符串都转换为小写,并(可选)按字母顺序对每个字符进行排序。
  2. 当字符串中至少包含一个相等的字符时,请从每个字符串中删除该字符的第一个实例。
  3. 添加剩余字符串的长度,并返回/输出结果。

如果输入是:

Hello, world!
Code golf!

然后,将它们转换为小写并排序:(按JS的默认排序;请注意前导空格)

 !,dehllloorw
 !cdefgloo

删除两个字符串中的所有字符,我们最终得到:

,hllrw
cfg

因此,原始两个字符串之间的字谜距离= 6 + 3 = 9。

细节

  • 字符串可以采用任何明智的格式。
  • 字符串将仅包含可打印的ASCII。
  • 字符串本身将不包含除常规空格以外的任何空格。(没有选项卡,换行符等)
  • 只要结果相同,就无需使用此精确算法。

测试用例

输入1:

Hello, world!
Code golf!

输出1:

9

输入2:

12345 This is some text.
.txet emos si sihT 54321

输出2:

0

输入3:

All unique characters here!
Bdfgjkmopvwxyz?

输出3:

42

输入4:

This is not exactly like Levenshtein distance,
but you'll notice it is quite similar.

输出4:

30

输入5:

all lowercase.
ALL UPPERCASE!

输出5:

8

计分

这是,因此以字节为单位的最短有效代码获胜。Tiebreaker提交的提交首先达到其最终字节数。获胜者将在10月12日下周一Monday选。祝您好运!

编辑:恭喜获胜者@isaacg,使用Pyth(再次)获得了惊人的12个字节!

*如果此算法已在其他地方使用和/或使用其他名称,请告诉我!经过20分钟的搜索,我找不到它。


将任务描述为“编写使用以下逻辑[做某事]的程序[…]”,然后再添加“您无需使用此确切算法[…]”,这有点矛盾。
爱德华2015年

@ÉdouardTrue; 感谢您指出了这一点。我相信现在会更好。
ETHproductions 2015年

又是星期二了。;)
Martin Ender 2015年

@MartinBüttner在没有wi-fi的路上行驶时,很难挑战。;)不用担心,我很快就会准备一个新的。
ETHproductions 2015年

Answers:


14

Pyth,12个字节

ls.-M.prR0.z

测试套件

有问题的运算等效于Pyth的袋式减法运算符, .-在两个方向上应用的。我想你可以称其为袋装异或。

解决方案是:

.z:获取输入作为2个字符串的列表。

rR0:将两者都转换为小写。

.p:形成所有排列,即正常和反向。

.-M:映射 .-在每个订单上操作。

s:连接结果。

l:打印长度。


而且我认为所有答案都可能太长了。
ETHproductions 2015年

8

JavaScript(ES7),92个字节

定义一个匿名函数。

要进行测试,请运行以下代码段。您可以编辑代码,然后单击“测试”以将其输出与原始代码进行比较。(如果发现改进,请留下评论!)输入就像"Hello, world!", "Code golf!"在输入框中一样。

感谢@ETHproductions节省了6个字节!


(a,b)=>[for(v of a[t="toLowerCase"]())if((b=b[t]())==(b=b.replace(v,"")))v][l="length"]+b[l]
<!--                               Try the test suite below!                              --><strong id="bytecount" style="display:inline; font-size:32px; font-family:Helvetica"></strong><strong id="bytediff" style="display:inline; margin-left:10px; font-size:32px; font-family:Helvetica; color:lightgray"></strong><br><br><pre style="margin:0">Code:</pre><textarea id="textbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><pre style="margin:0">Input:</pre><textarea id="inputbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><button id="testbtn">Test!</button><button id="resetbtn">Reset</button><br><p><strong id="origheader" style="font-family:Helvetica; display:none">Original Code Output:</strong><p><div id="origoutput" style="margin-left:15px"></div><p><strong id="newheader" style="font-family:Helvetica; display:none">New Code Output:</strong><p><div id="newoutput" style="margin-left:15px"></div><script type="text/javascript" id="golfsnippet">var bytecount=document.getElementById("bytecount");var bytediff=document.getElementById("bytediff");var textbox=document.getElementById("textbox");var inputbox=document.getElementById("inputbox");var testbtn=document.getElementById("testbtn");var resetbtn=document.getElementById("resetbtn");var origheader=document.getElementById("origheader");var newheader=document.getElementById("newheader");var origoutput=document.getElementById("origoutput");var newoutput=document.getElementById("newoutput");textbox.style.width=inputbox.style.width=window.innerWidth-50+"px";var _originalCode=null;function getOriginalCode(){if(_originalCode!=null)return _originalCode;var allScripts=document.getElementsByTagName("script");for(var i=0;i<allScripts.length;i++){var script=allScripts[i];if(script.id!="golfsnippet"){originalCode=script.textContent.trim();return originalCode}}}function getNewCode(){return textbox.value.trim()}function getInput(){try{var inputText=inputbox.value.trim();var input=eval("["+inputText+"]");return input}catch(e){return null}}function setTextbox(s){textbox.value=s;onTextboxChange()}function setOutput(output,s){output.innerHTML=s}function addOutput(output,data){output.innerHTML+='<pre style="background-color:'+(data.type=="err"?"lightcoral":"lightgray")+'">'+escape(data.content)+"</pre>"}function getByteCount(s){return(new Blob([s],{encoding:"UTF-8",type:"text/plain;charset=UTF-8"})).size}function onTextboxChange(){var newLength=getByteCount(getNewCode());var oldLength=getByteCount(getOriginalCode());bytecount.innerHTML=newLength+" bytes";var diff=newLength-oldLength;if(diff>0){bytediff.innerHTML="(+"+diff+")";bytediff.style.color="lightcoral"}else if(diff<0){bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgreen"}else{bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgray"}}function onTestBtn(evt){origheader.style.display="inline";newheader.style.display="inline";setOutput(newoutput,"");setOutput(origoutput,"");var input=getInput();if(input===null){addOutput(origoutput,{type:"err",content:"Input is malformed. Using no input."});addOutput(newoutput,{type:"err",content:"Input is malformed. Using no input."});input=[]}doInterpret(getNewCode(),input,function(data){addOutput(newoutput,data)});doInterpret(getOriginalCode(),input,function(data){addOutput(origoutput,data)});evt.stopPropagation();return false}function onResetBtn(evt){setTextbox(getOriginalCode());origheader.style.display="none";newheader.style.display="none";setOutput(origoutput,"");setOutput(newoutput,"")}function escape(s){return s.toString().replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}window.alert=function(){};window.prompt=function(){};function doInterpret(code,input,cb){var workerCode=interpret.toString()+";function stdout(s){ self.postMessage( {'type': 'out', 'content': s} ); }"+" function stderr(s){ self.postMessage( {'type': 'err', 'content': s} ); }"+" function kill(){ self.close(); }"+" self.addEventListener('message', function(msg){ interpret(msg.data.code, msg.data.input); });";var interpreter=new Worker(URL.createObjectURL(new Blob([workerCode])));interpreter.addEventListener("message",function(msg){cb(msg.data)});interpreter.postMessage({"code":code,"input":input});setTimeout(function(){interpreter.terminate()},1E4)}setTimeout(function(){getOriginalCode();textbox.addEventListener("input",onTextboxChange);testbtn.addEventListener("click",onTestBtn);resetbtn.addEventListener("click",onResetBtn);setTextbox(getOriginalCode())},100);function interpret(code,input){window={};alert=function(s){stdout(s)};window.alert=alert;console.log=alert;prompt=function(s){if(input.length<1)stderr("not enough input");else{var nextInput=input[0];input=input.slice(1);return nextInput.toString()}};window.prompt=prompt;(function(){try{var evalResult=eval(code);if(typeof evalResult=="function"){var callResult=evalResult.apply(this,input);if(typeof callResult!="undefined")stdout(callResult)}}catch(e){stderr(e.message)}})()};</script>

有关测试套件的更多信息


怎么运行的

//Define function w/ paramters a, b
(a,b)=>
     //lowercase a
     //for each character v in a:
     [for(v of a[t="toLowerCase"]())
          //lowercase b
          //remove the first instance of v in b
          //if b before removal equals b after removal (if nothing was removed):
          if((b=b[t]())==(b=b.replace(v,"")))
               //keep v in the array of a's values to keep
               v]
     //get the length of the computed array
     [l="length"]
     //add b's length
     +b[l]
     //implicitly return the sum

我已经在一个基于阵列的ES6答案上工作了一个小时,但只能将其降低到122。似乎我的方向不对!+1
ETHproductions 2015年

顺便说一句,您可以替换.join("")+b.join``+b无效。
ETHproductions 2015年

1
哇,您到底从哪里获得了该测试套件?这个棒极了!我希望我能+1三,四次......
ETHproductions

@ETHproductions谢谢!:DI实际上是我自己制作的测试套件。查看我的元信息!
jrich

我在那儿+1了,希望这里能弥补+5的不足。;)
ETHproductions 2015年

6

CJam,23个 19字节

2{'¡,lelfe=}*.-:z:+

CJam解释器中在线尝试

怎么运行的

2{         }*        Do the following twice:
  '¡,                  Push the string of the first 161 Unicode charcters.
     lel               Read a line from STDIN and convert it to lowercase.
        fe=            Count the number of occurrences of each of the 160
                       characters in the lowercased line.
             .-      Vectorized subtraction; push the differences of the
                     occurrences of all 161 characters.
               :z    Apply absolute value to each difference.
                 :+  Push the sum of all results.

4

Ruby,62岁

#!ruby -naF|
gets
p$F.count{|c|!$_.sub!(/#{Regexp.escape c}/i){}}+~/$/

一定有更好的方法。

编辑:57个字符,感谢iamnotmaynard调查了我懒得去的一条路。

#!ruby -naF|
gets.upcase!
p$F.count{|c|!$_.sub!(c.upcase){}}+~/$/

sub可以带弦。您不能使用c.downcase代替/#{Regexp.escape c}/i吗?
恢复莫妮卡iamnotmaynard

我不得不downcase两个字符串(或upcase等价。)
histocrat

嗯当然了 (尽管在我看来,这样做仍然可以为您节省几个字节。)
恢复莫妮卡iamnotmaynard 2015年

4

Python,90 87 81 80 79字节

lambda a,b,s=str.lower:sum(abs(s(a).count(c)-s(b).count(c)))for c in{*s(a+b)}))

Python <3.5版本,80字节

lambda a,b,s=str.lower:sum(abs(s(a).count(c)-s(b).count(c))for c in set(s(a+b)))

说明

对于a或b中的每个字符,计算每个字符串中出现的次数,然后加上(正)差。

编辑:重新读取规则,实现匿名功能是可以接受的,通过摆脱raw_input改进了答案。第一次打高尔夫球,请保持柔和!

感谢sp3000的改进,重新定义了str.lower,使我意识到不需要打印。还有空格。仍然在学习。

使用python> = 3.5,有一种更短的定义集的方法,因此可以在以前的版本中保存一个字节。


3

视网膜,40 20字节

感谢MartinBüttner,节省了20个字节。

将每一行放在其自己的文件中,并用\n文字换行符替换。

+i`(.)(.*\n.*)\1
$2
.

2

pb,648字节

^w[B!0]{t[B]vb[T]^>}vb[-1]w[X!0]{<t[64]w[T!0]{w[B!0]{b[B-1]v}^[Y]t[T-1]}}w[B!-1]{w[B=0]{b[27]}t[26]w[T!0]{w[B!0]{b[B-1]v}^[Y]t[T-1]}>}b[0]w[X!0]{<w[B!0]{b[1]v}^[Y]w[B=0]{b[32]}w[B=1]{b[0]}}^w[B!0]{t[B]vb[B+T]^>}vb[1]<w[B!9]{t[B]b[0]vv<[X]w[B!0]{>}b[T]^^<[X]w[B!0]{>}<}b[0]<w[X!-1]{t[B]vb[1]^w[B!1]{>}vvw[X!-1]{w[B=T]{b[0]<[X]^w[B!1]{>}^b[0]vt[2]}<}^[Y]vw[B!1]{>}b[0]^<}t[0]w[B!1]{w[B!0]{t[T+1]b[0]}>}b[0]vvw[X!-1]{w[B!0]{t[T+1]b[0]}<}>b[11]^b[T]w[B!0]{vw[B!11]{>}t[B]b[0]>b[T]<[X]^t[B]b[0]vw[B!11]{>}<w[T!0]{t[T-1]b[B+1]w[B=11]{b[0]^<[X]b[B+1]vw[B!11]{>}<}}^<[X]}vw[B!11]{b[B+48]>}b[0]<w[B!0]{w[B!0]{>}<t[B]^^<[X]w[B!0]{>}b[T]<[X]vvw[B!0]{>}<b[0]<}

使用带制表符的输入,将两个字符串分开。

这是一个傻瓜。实际上实现算法并不是困难的部分,这相对容易实现。但是我不得不做两件事,而这在pb中是很难做到的:不区分大小写和itoa。我碰巧有一个程序可以转换为小写字母(本身长211个字节),其他所有东西都放在最后以专门应对这一挑战。

您可以观看此程序在YouTube上运行!如果要这样做,请记住以下几点:

  • 对该版本的程序进行了稍微修改,重为650字节。唯一的区别是,将255用作标志值而不是-1,因为尝试打印chr(-1)在监视模式下运行时导致解释器崩溃。
  • 在视频的输入Hello, world!Code golf.。这与挑战中的示例输入之一略有不同;我使用它是因为它很短,但是对其进行了修改,因此正确的输出将是10而不是9。这只是为了证明即使数字是多个数字也可以正确打印,这在pb中很难。
  • 解释器很糟糕,它在这里显示。值得注意的是,制表符消除了空格,因此在大部分视频中都不会对齐,只要将字节设置为10,即使该语言仍将其视为一个“行”,它也会显示换行符,并且它只是将光标移到开始而不是清除屏幕的事实,这意味着视频中有时甚至不存在许多字符,它们只是从不离开那里。在pbi中对此有一些保护措施,但事实是chr(10)如果处理不当,将使它们在很大程度上无用。话虽这么说,我认为观看几乎是一种美丽。解释其他可怕代码的过程真是一团糟的可怕代码,其中的一些片段在您眼前破碎了,但是一切都足以得到正确的答案。看起来好像正在打印垃圾,但是如果您充分了解源代码,就可以随时了解其原因以及原因。观看此视频时,我感觉像Cypher:I... I don’t even see the code. All I see is blonde, brunette, red-head.

事不宜迟,这是未使用的代码。

### UNTIL FURTHER NOTICE, ALL CODE YOU SEE HERE   ###
### IS JUST A SIMPLE LOWERCASE PROGRAM. ALL INPUT ###
### IS PRINTED UNALTERED UNLESS ITS ASCII CODE IS ###
### IN [65, 90], IN WHICH CASE IT IS PRINTED WITH ###
### 32 ADDED TO IT.                               ###

^w[B!0]{t[B]vb[T]^>}    # Copy entire input to Y=0
                        # (If the program ended here, it would be cat!)
vb[-1]                  # Leave a flag at the end of the copy (important later)

# Next, this program will set each of those bytes to 0 or 32, then add the input again.
# A byte needs to be set to 32 iff it's in [65, 90].
# pb can't test > or <, only == and !=.
# A workaround:

# Set each byte to max((byte - 64), 0)



w[X!0]{<        # For each byte:
    t[64]         # Set T to 64 as a loop variable
    w[T!0]{       # While T != 0:
        w[B!0]{     # While the current byte not 0:
            b[B-1]v   # Subtract one from the current cell, then go down one
                      # (guaranteed to be 0 and kill the loop)
        }
        ^[Y]        # Brush is at Y=0 or Y=1 and needs to be at Y=0.
                    # ^[Y] always brings brush to Y=0
        t[T-1]      # T--
    }
}

# Bytes that are currently 0 need to be 0.
# Bytes that are currently in [27, inf) need to be 0.
# Bytes in [1, 26] need to be 32.

# Set bytes that are equal to 0 to 27
# The only groups that have to be worried about are >26 and =<26.

# Then set each byte to max((byte - 26), 0)

w[B!-1]{         # Until we hit the flag:
    w[B=0]{b[27]}   # Set any 0 bytes to 27
    t[26]           # T as loop variable again
    w[T!0]{         # While T != 0:
        w[B!0]{       # While the current byte not 0:
            b[B-1]v     # Subtract one from the current cell, then go down one
                        # (guaranteed to be 0 and kill the loop)
        }
        ^[Y]          # Brush is at Y=0 or Y=1 and needs to be at Y=0.
                      # ^[Y] always brings brush to Y=0
        t[T-1]        # T--
    }
>}
b[0]              # Clear the flag

# Set bytes that are equal to 0 to 32
# All others to 0

w[X!0]{<          # For each byte:
    w[B!0]{       # While the current byte not 0:
        b[1]v       # Set it to 1, then go down one
                    # (guaranteed to be 0 and kill the loop)
    }
    ^[Y]          # Back to Y=0 no matter what
    w[B=0]{b[32]} # Set 0 bytes to 32
    w[B=1]{b[0]}  # Set 1 bytes to 0
}

# Any byte that had a capital letter is now 32. All others are 0.
# Add the original values to the current values to finish.

^w[B!0]{          # For each byte OF ORIGINAL INPUT:
    t[B]vb[B+T]^>   # Add it to the space below
}

### ABOVE IS THE ENTIRE LOWERCASE PROGRAM. THE    ###
### REST OF THE CODE IMPLEMENTS THE ALGORITHM.    ###

vb[1]            # Leave a flag after the end, guaranteed to be further right
                 # than anything else

<w[B!9]{         # Starting from the end, until hitting a tab:
    t[B]b[0]        # Store the last byte and erase it
    vv<[X]          # Go down two columns and all the way to the left
    w[B!0]{>}       # Go right until reaching an empty space
    b[T]            # Print the stored byte
    ^^<[X]w[B!0]{>} # Go back to the end of the first line
    <
}

b[0]              # Erase the tab
<w[X!-1]{         # For each byte in the first line:
    t[B]            # Store that byte
    vb[1]           # Mark that byte to be found later
    ^w[B!1]{>}      # Find the flag at the end
    vvw[X!-1]{      # For everything in the other line:
        w[B=T]{       # If the current byte is the same as the saved byte:
            b[0]        # Set it to 0
            <[X]^       # Go to the beginning of line 2
            w[B!1]{>}   # Find the marker for where the program is working in line 1
            ^b[0]v      # Set that byte that the program is working on to 0
            t[2]        # Stay on line 2 and start looking for a 2 (will never appear)
                        # (If this block was entered, it basically breaks the outer loop.)
        }
        <
    }
    ^[Y]v           # Ensure that the brush is on Y=1
    w[B!1]{>}       # Find the marker for where the program is working in line 1
    b[0]^<          # Erase the marker and start working on the next byte
}

t[0]              # Set T to 0. It's going to be used for counting the remaining bytes.

w[B!1]{           # Until hitting the flag at the very right:
    w[B!0]{         # If the current byte is not 0:
        t[T+1]        # Add 1 to T
        b[0]          # Set the current byte to 0
    }
    >
}
b[0]              # Clear the flag

vvw[X!-1]{        # Same as above, but for Y=2
    w[B!0]{
        t[T+1]
        b[0]
    }
    <
}

# T now contains the number that needs to be printed!!
# Now, to print out a number in decimal...

>b[11]            # A flag that shows the end of the number
                  # (so 0 digits aren't confused for other empty spaces on the canvas)
^b[T]             # The number to be converted to digits
w[B!0]{           # While the number to be converted is not 0:
    vw[B!11]{>}     # Go to the flag
    t[B]b[0]>b[T]   # Move it right
    <[X]^t[B]b[0]   # Store the number to be converted to digits to T and clear its space on the canvas
    vw[B!11]{>}<    # Go to the left of the flag
    w[T!0]{         # While T is not 0:
        t[T-1]        # T--
        b[B+1]        # B++
        w[B=11]{      # If B is 10:
            b[0]        # Set it back to 0
            ^<[X]b[B+1]   # Add 1 to a counter to be converted after
            vw[B!11]{>}<  # Go back to continue converting T
        }
    }
^<[X]}

vw[B!11]{         # Add 48 to all digits to get correct ASCII value
    b[B+48]>
}

b[0]              # Clear the flag value, 0s now appear as 48 instead of 0 so it is unnecessary

<w[B!0]{          # While there are digits on Y=2:
    w[B!0]{>}<      # Go to the last one
    t[B]            # Save it to T
    ^^<[X]          # Go to (0, 0)
    w[B!0]{>}       # Go right until finding an empty space
    b[T]            # Print the digit in T
    <[X]vvw[B!0]{>} # Go to the end of Y=2
    <b[0]           # Erase it
    <               # Repeat until finished. :)
}

2

C ++ 199字节

使用数组存储第一个字符串中每个字符的计数,最小化第二个字符串中的计数。接下来,它找到数组元素的绝对值的总和:这是距离。

打高尔夫球:

#define L(c) c<91&c>64?c+32:c
int d(char*a,char*b){int l[128];int i=128,s=0;for(;i-->0;)l[i]=0;for(;a[++i];)l[L(a[i])]++;for(i=-1;b[++i];)l[L(b[i])]--;for(i=0;++i<128;)s+=i[l]>0?i[l]:-i[l];return s;}

取消高尔夫:

#define L(c) (c<='Z' && c>='A' ? c+'a'-'A':c)
//convert to lower case
int dist(char a[],char b[]){
  int l[128];
  int i = 128, s = 0;

  for(;i-->0;)
    l[i]=0;

  for(;a[++i]!='\0';)
    l[L(a[i])]++;

  for(i=-1;b[++i]!='\0';)
    l[L(b[i])]--;

  for(i=0;++i<128;)
    s+=i[l]>0?i[l]:-i[l];

  return s;
}

1

PowerShell,79个字节

param($a,$b)$a=[char[]]$a.ToLower();$b=[char[]]$b.ToLower();(diff $a $b).Length

几乎与我在Anagram Code Golf上的答案完全相同的代码...但是...如果我只是-eq0从那个答案中剪掉,我会得到一些奇怪的行为,因此我不得不明确声明.ToLower()并在param声明之外重铸。+

解释(大多数情况下)也从该答案中复制而来-接受两个字符串输入,将它们变为小写,然后将它们重新转换为字符数组。该diff函数(的别名Compare-Object)接受两个数组,并返回两者之间不同的项目。通过将return作为一个数组重新铸造(),然后检查其长度,我们可以利用它。

+例如,我param([char[]]$a,[char[]]$b)(diff $a $b).lengthall lowercase./ 上得到了虚假结果ALL UPPERCASE!测试中。如果我手动分离出数组(例如ran (diff ('a','l','l'...),它可以正常工作,但每次与转换之间存在大写/小写字母重叠时,它都会失败。我在文档上可以阅读的所有内容都diff默认情况下不区分大小写,所以…… 耸耸肩???


很奇怪。其他任何情况(即使大小写敏感度不同)也不需要它。
Jonathan Leech-Pepin

1

巴什68 67字节

f()(fold -w1<<<"$1"|sort)
diff -i <(f "$1") <(f "$2")|grep -c ^.\ 

一世 认为这可行。注意第二行上的尾随空格。

测试用例

$ ./anagram "Hello, world!" "Code golf!"
9
$ ./anagram "12345 This is some text." ".txet emos si sihT 54321"
0
$ ./anagram "All unique characters here!" "Bdfgjkmopvwxyz?"
42
$ ./anagram "This is not exactly like Levenshtein distance," "but you'll notice it is quite similar."
30
$ ./anagram "all lowercase." "ALL UPPERCASE!"
8

1

Perl,52 46字节+ 3个开关(a,F,n)= 55 49字节

# 49 bytes (prefix 'x' to all characters so that values() could be removed)
perl -naF -E 'END{$c+=abs for%a;say$c}$a{x.lc}+=2*$.-3 for@F'

# 55 bytes
perl -naF -E 'END{$c+=abs for values%a;say$c}$a{+lc}+=2*$.-3 for@F'

从STDIN接受输入,并在其自己的行中输入字符串,并以EOF终止。

开关:

-aF splits each input line into characters and stores this into @F
-n  loop over all input lines
-E  Execute the script from the next arg

码:

# %a is the hash counting the occurances of the lowercase characters
# $. has the line number. Thus, 2*$.-3 is -1 for line 1 and +1 for line 2
$a{+lc}+=2*$.-3 for @F

# In the end (assuming 2 lines have been read), sum up the absolute values
# from the hash %a. Note that if a character occured more times in string 1
# its value be negative, if more in string 2 then positive, otherwise 0.
END {
    $c+=abs for values %a;
    say $c
}

1

Bash + GNU utils,53

S(){ sed 's/./\L&\n/g'|sort;};S>1;S|comm -3 1 -|wc -l

sed转换为小写字母,并将字符串分割为sort。由于我们需要执行两次此操作,因此将其放入函数中。 comm3 -3过滤掉相关行并wc -l产生数字。

输入是通过STDIN;由于两个命令是按顺序读取的,因此必须EOF在字符串之间和末尾发送两次(Ctrl-D)。覆盖文件1(如果存在)。


1

Matlab,91字节

function r=f(s,t)
s=lower(s);t=lower(t);u=unique([s t]);r=sum(abs(histc(s,u)-histc(t,u)));

在线尝试

其工作原理如下:

  1. 将字符串转换为小写。
  2. 查找唯一字符两个字符串。也就是说,确定字符串中曾经出现的所有字符。
  3. 计算每个字符串的直方图。即,对于每个字符串,查找在步骤2中获得的每个字符出现多少次。
  4. 减去直方图并取差的绝对值。这表示一个字符再出现在一个字符串中的次数多于在。
  5. 结果是这些绝对差异的总和。

这似乎太长了-您确定它是最佳选择吗?
lirtosiast,2015年

@ThomasKwa不,一点也不:-)
路易斯·门多


0

F#,134126字节

let g=Seq.countBy Char.ToLower>>List.ofSeq
let f a b=g a@g b|>Seq.groupBy fst|>Seq.sumBy(snd>>Seq.map snd>>Seq.reduce(-)>>abs)

说明

  1. 计算每个(小写)字符在a和中出现的次数b分开。
  2. 将计数按共同特征分组
  3. -运算符来减少每个组,这具有以下效果:

    • 如果仅找到一个值(即字符仅出现在一个输入中),则返回该值。
    • 如果找到两个值(即字符出现在两个输入中),则从第一个值中减去第二个值。
  4. 对上一步中的值的绝对值求和。


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.