Segunda-feira Mini-Golf # 3: Distância do anagrama

24

Mini-golfe de segunda-feira: Uma série de desafios curtos , publicados (espero!) Toda segunda-feira.
(Desculpe, este está um pouco atrasado.)

Tenho certeza que a maioria de vocês já ouviu falar da distância de Levenshtein , um algoritmo para calcular a distância entre duas cordas. Bem, esse desafio é sobre a implementação de um algoritmo semelhante de minha própria invenção *, chamado distância do anagrama . A principal diferença é que a ordem dos personagens não importa; em vez disso, apenas os caracteres exclusivos de uma sequência ou de outra são medidos.

Desafio

O objetivo do desafio é escrever um programa ou função que pegue duas cordas e retorne a distância do anagrama entre elas. A principal maneira de fazer isso é usar a seguinte lógica:

  1. Converta as duas strings em minúsculas e (opcionalmente) classifique os caracteres de cada um em ordem alfabética.
  2. Enquanto as seqüências contêm pelo menos um caractere igual, remova a primeira instância desse caractere de cada sequência.
  3. Adicione os comprimentos das seqüências restantes e retorne / produza o resultado.

Exemplo

Se as entradas são:

Hello, world!
Code golf!

Em seguida, em minúsculas e classificadas, elas se tornam: (pela classificação padrão de JS; observe os espaços iniciais)

 !,dehllloorw
 !cdefgloo

Removendo todos os caracteres que estão nas duas cadeias, terminamos com:

,hllrw
cfg

Assim, a distância do anagrama entre as duas cordas originais = 6 + 3 = 9.

Detalhes

  • As seqüências de caracteres podem ser obtidas em qualquer formato sensato.
  • As seqüências consistirão apenas em ASCII imprimível.
  • As cadeias de caracteres em si não conterão nenhum espaço em branco além dos espaços regulares. (Sem guias, novas linhas etc.)
  • Você não precisa usar esse algoritmo exato, desde que os resultados sejam os mesmos.

Casos de teste

Entrada 1:

Hello, world!
Code golf!

Saída 1:

9

Entrada 2:

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

Saída 2:

0

Entrada 3:

All unique characters here!
Bdfgjkmopvwxyz?

Saída 3:

42

Entrada 4:

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

Saída 4:

30

Entrada 5:

all lowercase.
ALL UPPERCASE!

Saída 5:

8

Pontuação

Este é o , pelo que o código válido mais curto em bytes vence. O desempatador vai para o envio que atingiu sua contagem final de bytes primeiro. O vencedor será escolhido na próxima segunda-feira, 12 de outubro. Boa sorte!

Edit: Parabéns ao vencedor, @isaacg, usando Pyth (novamente) por 12 bytes surpreendentes !

* Se este algoritmo foi usado em outro lugar e / ou recebeu outro nome, informe-me! Não consegui encontrá-lo com uma pesquisa de 20 minutos.

ETHproductions
fonte
Descrever a tarefa como “escrever um programa […] que [faz coisas] usando a lógica a seguir” para adicionar posteriormente “Você não precisa usar esse algoritmo exato […]” é um pouco contraditório.
Édouard
@ Édouard True; Obrigado por apontar isso. Eu acredito que está melhor agora.
ETHproductions
Já é terça-feira novamente. ;)
Martin Ender
@ MartinBüttner É meio difícil escrever um desafio enquanto você está na estrada sem wi-fi. ;) Não se preocupe, vou ter um novo pronto daqui a pouco.
ETHproductions

Respostas:

14

Pitão, 12 bytes

ls.-M.prR0.z

Suíte de teste

A operação em questão é equivalente ao operador de subtração bagwise de Pyth .-, aplicado nas duas direções. Você poderia chamar isso de bagor xor, suponho.

A solução é:

.z: obtém entrada como lista de 2 strings.

rR0: converte ambos para minúsculas.

.p: Forme todas as permutações, ou seja, normais e invertidas.

.-M: Mapeie a .-operação sobre cada pedido.

s: Concatene os resultados.

l: Imprima o comprimento.

isaacg
fonte
E eu pensei que todas as respostas poderiam ser muito longas ... Muito bem!
ETHproductions
8

JavaScript (ES7), 92 bytes

Define uma função anônima.

Para testar, execute o snippet abaixo. Você pode editar o código e clicar em 'Teste' para comparar sua saída com a original. (Deixe um comentário se encontrar uma melhoria!) A entrada é como "Hello, world!", "Code golf!"na caixa de entrada.

Obrigado a @ETHproductions por economizar 6 bytes!


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

Mais sobre a suíte de testes


Como funciona

//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
jrich
fonte
Eu estava trabalhando em uma resposta ES6 baseada em matriz por uma hora e só consegui reduzi-la para 122. Parece que estava olhando na direção errada! +1
ETHproductions
BTW, você poderia substituir .join("")+bcom .join``+bsem efeito.
ETHproductions
11
Uau, onde você conseguiu essa suíte de testes? É brilhante! Eu gostaria de poder +1 três ou quatro vezes mais ....
ETHproductions
@ETHproductions Obrigado! : Eu próprio fiz a suíte de testes. Confira meu meta post!
jrich
Eu marquei com +1 lá, espero que compense por não poder +5 aqui. ;)
ETHproductions
6

CJam, 23 19 bytes

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

Experimente online no intérprete CJam .

Como funciona

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.
Dennis
fonte
4

Ruby, 62

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

Tem que haver uma maneira melhor.

Edit: 57 caracteres graças a iamnotmaynard investigando um caminho que eu estava com preguiça de fazer.

#!ruby -naF|
gets.upcase!
p$F.count{|c|!$_.sub!(c.upcase){}}+~/$/
histocrata
fonte
subpode levar cordas. Você não poderia usar em c.downcasevez de /#{Regexp.escape c}/i?
Reintegrar Monica iamnotmaynard
Eu teria que downcase ambas as cordas (ou upcase, de forma equivalente.)
histocrat
Ah, claro. (Embora me pareça que isso ainda economizaria alguns bytes.)
Reponha Monica iamnotmaynard
4

Python, 90 87 81 80 79 bytes

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

Python <versão 3.5, 80 bytes

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

Explicação

Para cada caractere em a ou b, conte o número de ocorrências em cada sequência e adicione a diferença (positiva).

Edit: Reler regras, funções anônimas realizadas são aceitáveis, melhor resposta, eliminando raw_input. Primeiro golfe, por favor, seja gentil!

Obrigado ao sp3000 pela melhoria da redefinição do str.lower e por me fazer perceber que a impressão era desnecessária. Também espaços. Ainda aprendendo.

Usando python> = 3.5, existe uma maneira mais curta de definir conjuntos, para que um byte possa ser salvo em versões anteriores.

Mego
fonte
3

Retina, 40 20 bytes

20 bytes salvos graças a Martin Büttner.

Coloque cada linha em seu próprio arquivo e substitua \npor uma nova linha literal.

+i`(.)(.*\n.*)\1
$2
.
O número um
fonte
2

pb , 648 bytes

^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]<}

Recebe uma entrada com um caractere de tabulação que separa as duas cadeias.

Este foi um doozy. Na verdade, implementar o algoritmo não foi a parte mais difícil, veio com relativa facilidade. Mas eu tive que fazer duas coisas que são difíceis de fazer no pb: insensibilidade ao caso e itoa. Por acaso, eu tinha um programa de conversão para minúsculas (com apenas 211 bytes de comprimento) e todo o resto foi pregado no final para fazer o trabalho especificamente para esse desafio.

Você pode assistir a este programa executado no YouTube! Há algumas coisas que você deve ter em mente se fizer:

  • Esta versão do programa é ligeiramente modificada, pesando 650 bytes. A única diferença é que 255 é usado como um valor de sinalizador em vez de -1, porque tentar imprimir chr(-1)trava o intérprete ao executar no modo de exibição.
  • A entrada nesse vídeo é Hello, world!e Code golf.. Isso é um pouco diferente de uma das entradas de exemplo no desafio; Usei-o porque era curto, mas o modifiquei para que a saída correta seja 10 em vez de 9. Isso é apenas para mostrar que o número é impresso corretamente, mesmo se houver vários dígitos, o que é difícil em pb.
  • O intérprete é horrível e mostra aqui. Notavelmente, o caractere de tabulação diminui o espaçamento para que as coisas não fiquem alinhadas em grandes partes do vídeo, sempre que um byte é definido como 10, ele mostra uma quebra de linha, mesmo que o idioma ainda considere uma "linha" e o fato de apenas mover o cursor para o início, em vez de limpar a tela, significa que ocasionalmente há um número de caracteres no vídeo que nem sequer estão lá, eles simplesmente nunca desapareceram quando estavam lá. Existem algumas proteções contra isso no pbi, mas o fato de quechr(10)não é tratado adequadamente os torna amplamente inúteis aqui. Tudo isso dito, eu acho que é quase bonito de se assistir. É uma enorme bagunça de código horrível interpretando outro código horrível, partes dele quebrando na frente dos seus olhos e, no entanto, tudo funciona apenas o suficiente para obter a resposta certa. Parece que o lixo está sendo impresso, mas se você observar de perto o suficiente com o conhecimento da fonte, poderá descobrir o que está fazendo e o porquê a qualquer momento. Eu me sinto como Cypher quando assisto a este vídeo:I... I don’t even see the code. All I see is blonde, brunette, red-head.

Sem mais delongas, aqui está o código não destruído.

### 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. :)
}
undergroundmonorail
fonte
2

C ++ 199 bytes

Usa uma matriz para armazenar a contagem de cada caractere na primeira sequência, minis a contagem na segunda sequência. A seguir, encontra a soma dos valores absolutos dos elementos da matriz: essa é a distância.

Golfe:

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

Ungolfed:

#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;
}
MegaTom
fonte
1

PowerShell, 79 bytes

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

Quase exatamente o mesmo código da minha resposta no Anagram Code Golf ... mas ... Eu estou tendo um comportamento estranho se eu simplesmente retirar -eq0essa resposta, então acabei precisando explicitamente .ToLower()e reformular fora da paramdeclaração. +

A explicação também (principalmente) foi copiada dessa resposta - Pega as duas entradas de seqüência de caracteres, as torna em minúsculas e as reintroduz como matrizes de caracteres. A difffunção (um alias para Compare-Object) pega as duas matrizes e retorna itens diferentes entre as duas. Aproveitamos isso ao relançar o retorno como uma matriz com ()e, em seguida, verificar seu comprimento.

+ Por exemplo, eu estava ficando resultados falsos com param([char[]]$a,[char[]]$b)(diff $a $b).lengtho all lowercase./ ALL UPPERCASE!teste. Se eu separasse manualmente as matrizes (por exemplo, executei(diff ('a','l','l'... ), funcionaria bem, mas falharia toda vez que houvesse sobreposição de maiúsculas / minúsculas na transmissão. Tudo o que posso ler na documentação afirma que não diffdiferencia maiúsculas de minúsculas por padrão, então ... encolher de ombros ???

AdmBorkBork
fonte
Muito estranho. Não é necessário para nenhum dos outros casos (mesmo com distinção entre maiúsculas e minúsculas).
Jonathan Leech-Pepin
1

Bash, 68 67 bytes

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

Eu acho que isso funciona. Observe o espaço à direita na segunda linha.

Casos de teste

$ ./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
Dennis
fonte
1

Perl, 52 46 bytes + 3 comutadores (a, F, n) = 55 49 bytes

# 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'

Recebe a entrada do STDIN com as seqüências de entrada em suas próprias linhas, finalizadas pelo EOF.

Comuta:

-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

Código:

# %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
}
svsd
fonte
1

Utilitários Bash + GNU, 53

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

sedtransforma em minúsculas e divide a string em linhas para sort. Como precisamos fazer isso duas vezes, coloco-o em uma função. comm3 -3filtra as linhas relevantes e wc -lproduz o número.

Entrada é via STDIN; Como dois comandos são lidos seqüencialmente, você deve enviar EOF(Ctrl-D) duas vezes, entre as strings e no final. Sobrescreve o arquivo 1, se presente.

xebtl
fonte
1

Matlab, 91 bytes

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

Experimente online .

Isso funciona da seguinte maneira:

  1. Converte as seqüências de caracteres em minúsculas.
  2. Encontra os caracteres exclusivos das duas seqüências juntos. Ou seja, determina todos os caracteres que aparecem nas strings.
  3. Calcula o histograma de cada sequência. Ou seja, para cada seqüência de caracteres encontra quantas vezes cada um dos caracteres obtidos na etapa 2 aparece.
  4. Subtrai os histogramas e assume o valor absoluto das diferenças. Isso representa quantas vezes um caractere aparece em uma string mais do que na outra.
  5. O resultado é a soma dessas diferenças absolutas.
Luis Mendo
fonte
Parece muito tempo - você tem certeza de que é o ideal?
lirtosiast
@ThomasKwa Não, não em todos :-)
Luis Mendo
0

F #, 134 126 bytes

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)

Explicação :

  1. Conte o número de vezes que cada caractere (em minúsculas) aparece em ae bseparadamente.
  2. Agrupe as contagens por seu caráter comum
  3. Reduza cada grupo com o -operador, que tem o seguinte efeito:

    • Se apenas um valor for encontrado (ou seja, o caractere apareceu em apenas uma entrada), esse valor será retornado.
    • Se dois valores forem encontrados (ou seja, o caractere apareceu nas duas entradas) subtraia o segundo valor do primeiro.
  4. Soma o valor absoluto dos valores da etapa anterior.

pswg
fonte
0

Scala , 134 81 bytes

Obrigado @ ASCII-only por seu trabalho.

(s,t)=>{var k::l::_=List(s,t)map(_.toLowerCase.toBuffer)
((k--l)++(l--k)).length}

Experimente online!

V. Courtois
fonte
81
somente ASCII
ew, eu perdi isso, eu tenho coisas para aprender em scalagolf
V. Courtois
Haha, provavelmente tenho mais coisas para aprender. O primeiro é Scala: P
somente ASCII
esses truques foram bons embora.
V. Courtois