Lunes Mini-Golf # 3: distancia de anagrama


24

Mini golf de lunes: una serie de desafíos de corto , publicados (¡con suerte!) Todos los lunes
(Lo siento, esto es un poco tarde).

Estoy seguro de que la mayoría de ustedes han oído hablar de la distancia de Levenshtein , un algoritmo para calcular la distancia entre dos cadenas. Bueno, este desafío se trata de implementar un algoritmo similar de mi propia invención *, llamado distancia de anagrama . La principal diferencia es que el orden de los personajes no importa; en cambio, solo se miden los caracteres que son únicos para una cadena u otra.

Reto

El objetivo del desafío es escribir un programa o función que tome dos cadenas y devuelva la distancia del anagrama entre ellas. La forma principal de hacer esto es usar la siguiente lógica:

  1. Convierta ambas cadenas a minúsculas y (opcionalmente) ordene alfabéticamente los caracteres de cada uno.
  2. Si bien las cadenas contienen al menos un carácter igual, elimine la primera instancia de este carácter de cada cadena.
  3. Agregue las longitudes de las cadenas restantes y devuelva / envíe el resultado.

Ejemplo

Si las entradas son:

Hello, world!
Code golf!

Luego, en minúsculas y ordenadas, se convierten en: (según la clasificación predeterminada de JS; tenga en cuenta los espacios iniciales)

 !,dehllloorw
 !cdefgloo

Eliminando todos los caracteres que están en ambas cadenas, terminamos con:

,hllrw
cfg

Por lo tanto, la distancia del anagrama entre las dos cadenas originales = 6 + 3 = 9.

Detalles

  • Las cadenas pueden tomarse en cualquier formato sensible.
  • Las cadenas consistirán solo en ASCII imprimible.
  • Las cadenas en sí no contendrán ningún espacio en blanco que no sean espacios regulares. (Sin pestañas, líneas nuevas, etc.)
  • No necesita usar este algoritmo exacto, siempre que los resultados sean los mismos.

Casos de prueba

Entrada 1:

Hello, world!
Code golf!

Salida 1:

9

Entrada 2:

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

Salida 2:

0

Entrada 3:

All unique characters here!
Bdfgjkmopvwxyz?

Salida 3:

42

Entrada 4:

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

Salida 4:

30

Entrada 5:

all lowercase.
ALL UPPERCASE!

Salida 5:

8

Tanteo

Este es el , por lo que gana el código válido más corto en bytes. Tiebreaker va a la presentación que alcanzó su conteo final de bytes primero. El ganador será elegido el próximo lunes 12 de octubre. ¡Buena suerte!

Editar: ¡ Felicidades al ganador, @isaacg, usando Pyth (nuevamente) por unos asombrosos 12 bytes!

* Si este algoritmo se ha utilizado en otro lugar y / o se le ha dado otro nombre, ¡hágamelo saber! No pude encontrarlo con una búsqueda de 20 minutos.


Describir la tarea como "escribir un programa [...] que [hace cosas] usando la siguiente lógica" para luego agregar "No necesita usar este algoritmo exacto [...]" es un poco contradictorio.
Édouard

@ Édouard True; gracias por señalar eso. Creo que es mejor ahora.
ETHproductions

Ya es martes otra vez. ;)
Martin Ender

@ MartinBüttner Es un poco difícil escribir un desafío mientras estás en la carretera sin wi-fi. ;) No te preocupes, tendré uno nuevo listo en un momento.
ETHproductions

Respuestas:


14

Pyth, 12 bytes

ls.-M.prR0.z

Banco de pruebas

La operación en cuestión es equivalente al operador de resta en bolsa de Pyth .-, aplicado en ambas direcciones. Podrías llamarlo bagwise xor, supongo.

La solucion es:

.z: obtener entrada como lista de 2 cadenas.

rR0: convierte ambos a minúsculas.

.p: Forma todas las permutaciones, es decir, normales e invertidas.

.-M: Mapea la .-operación sobre cada pedido.

s: Concatenar los resultados.

l: Imprime la longitud.


Y pensé que todas las respuestas podrían ser demasiado largas ... ¡Bien hecho!
ETHproductions

8

JavaScript (ES7), 92 bytes

Define una función anónima.

Para probar, ejecute el fragmento a continuación. Puede editar el código y hacer clic en 'Probar' para comparar su salida con el original. (¡Deja un comentario si encuentras una mejora!) La entrada es como "Hello, world!", "Code golf!"en el cuadro de entrada.

¡Gracias a @ETHproductions por guardar 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>

Más sobre el conjunto de pruebas


Cómo 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

Había estado trabajando en una respuesta ES6 basada en matriz durante una hora, y solo había podido bajarla a 122. ¡Parece que estaba mirando en la dirección equivocada! +1
ETHproductions

Por cierto, se podría reemplazar .join("")+bcon .join``+bsin efecto.
ETHproductions

1
Wow, ¿de dónde demonios conseguiste ese conjunto de pruebas? ¡Es brillante! Desearía poder hacer +1 tres o cuatro veces más ...
ETHproductions

@ETHproductions ¡Gracias! : DI hice el conjunto de pruebas yo mismo, en realidad. ¡Mira mi meta publicación!
jrich

Hice +1 allí, espero que compense no poder hacer +5 aquí. ;)
ETHproductions

6

CJam, 23 19 bytes

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

Pruébelo en línea en el intérprete de CJam .

Cómo 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.

4

Rubí, 62

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

Tiene que haber una mejor manera.

Editar: 57 caracteres gracias a iamnotmaynard investigando un camino para el que era demasiado vago.

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

subpuede tomar hilos. ¿No podrías usar en c.downcaselugar de /#{Regexp.escape c}/i?
Restablecer Monica iamnotmaynard

Tendría que downcase ambas cadenas (o upcase, de manera equivalente.)
histocrat

Ah, por supuesto. (Aunque me parece que hacerlo aún le ahorraría un par de bytes.)
Vuelva a instalar Monica iamnotmaynard el

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 <versión 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)))

Explicación

Para cada carácter en aob, cuente el número de ocurrencias en cada cadena y agregue la diferencia (positiva).

Editar: volver a leer las reglas, las funciones anónimas realizadas son aceptables, la respuesta mejorada al deshacerse de raw_input. ¡Primer golf, por favor sea gentil!

Gracias a sp3000 por la mejora de redefinir str.lower y hacerme darme cuenta de que la impresión era innecesaria. También espacios. Aún aprendiendo.

Usando python> = 3.5, hay una forma más corta de definir conjuntos, por lo que se puede guardar un byte sobre versiones anteriores.


3

Retina, 40 20 bytes

20 bytes guardados gracias a Martin Büttner.

Coloque cada línea en su propio archivo y reemplácela \ncon una nueva línea literal.

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

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

Toma entrada con un carácter de tabulación que separa las dos cadenas.

Este fue un doozy. En realidad, implementar el algoritmo no fue la parte difícil, eso fue relativamente fácil. Pero tuve que hacer dos cosas que son difíciles de hacer en pb: insensibilidad a mayúsculas y minúsculas. Tuve un programa para convertir a minúsculas simplemente por ahí (211 bytes de longitud) y todo lo demás fue agregado al final para hacer el trabajo específicamente para este desafío.

¡Puedes ver este programa en YouTube! Hay algunas cosas que debe tener en cuenta si lo hace:

  • Esta versión del programa está ligeramente modificada, con un peso de 650 bytes. La única diferencia es que 255 se usa como un valor de indicador en lugar de -1, porque al intentar imprimir se chr(-1)bloquea el intérprete cuando se ejecuta en modo de observación.
  • La entrada en ese video es Hello, world!y Code golf.. Esto es ligeramente diferente de una de las entradas de ejemplo en el desafío; Lo usé porque era corto pero lo modifiqué para que la salida correcta fuera 10 en lugar de 9. Esto es solo para mostrar que el número se imprime correctamente incluso si tiene varios dígitos, lo cual es difícil en pb.
  • El intérprete es horrible, y se nota aquí. Notablemente, el carácter de tabulación elimina el espacio para que las cosas no estén alineadas en grandes porciones del video, cada vez que un byte se establece en 10, muestra un salto de línea a pesar de que el lenguaje todavía lo considera una "línea", y El hecho de que solo mueva el cursor al inicio en lugar de borrar la pantalla significa que ocasionalmente hay una serie de caracteres en el video que ni siquiera están allí, simplemente nunca se alejaron de cuando estaban allí. Hay algunas protecciones contra esto en pbi pero el hecho de quechr(10)no se maneja adecuadamente hace que sean en gran medida inútiles aquí. Dicho todo esto, creo que es casi algo hermoso de ver. Es un gran lío de código horrible interpretando otro código horrible, partes de él rompiéndose ante tus ojos, y sin embargo, todo funciona lo suficiente como para obtener la respuesta correcta. Parece que se está imprimiendo basura, pero si observa con suficiente atención con el conocimiento de la fuente, puede ver lo que está haciendo y por qué en cualquier momento. Me siento como Cypher cuando veo este video:I... I don’t even see the code. All I see is blonde, brunette, red-head.

Sin más preámbulos, aquí está el código sin golf.

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

Utiliza una matriz para almacenar el recuento de cada carácter en la primera cadena, minis el recuento en la segunda cadena. Luego encuentra la suma de los valores absolutos de los elementos de la matriz: esta es la distancia.

Golfizado:

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

Sin golf:

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

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

Casi exactamente el mismo código que mi respuesta en Anagram Code Golf ... pero ... estoy obteniendo un comportamiento extraño si solo elimino la -eq0respuesta, así que terminé necesitando explícitamente .ToLower()y refundir fuera de la paramdeclaración. +

La explicación también se copió (principalmente) de esa respuesta: toma las dos entradas de cadena, las pone en minúsculas y las vuelve a emitir como matrices de caracteres. La difffunción (un alias para Compare-Object) toma las dos matrices y devuelve elementos que son diferentes entre las dos. Aprovechamos eso volviendo a emitir el retorno como una matriz con (), y luego verificando su longitud.

+ Por ejemplo, estaba obteniendo resultados falsos con param([char[]]$a,[char[]]$b)(diff $a $b).lengthel all lowercase./ ALL UPPERCASE!test. Si separé manualmente las matrices (p. Ej., Ejecuté (diff ('a','l','l'...), funcionó bien, pero fallaba cada vez que había una superposición de mayúsculas / minúsculas con la conversión. Todo lo que puedo leer en la documentación indica que diffno distingue entre mayúsculas y minúsculas por defecto, así que ... ¿encogerse de hombros?


Muy raro. No es necesario para ninguno de los otros casos (incluso con diferentes mayúsculas y minúsculas).
Jonathan Leech-Pepin

1

Bash, 68 67 bytes

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

Creo que esto funciona. Tenga en cuenta el espacio final en la segunda línea.

Casos de prueba

$ ./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 bytes + 3 conmutadores (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'

Toma la entrada de STDIN con las cadenas de entrada en sus propias líneas, terminadas por EOF.

Interruptores:

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

1

Bash + GNU utils, 53

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

sedse transforma en minúsculas y divide la cadena en líneas para sort. Como tenemos que hacer esto dos veces, lo pongo en una función. comm3 -3filtra las líneas relevantes y wc -lproduce el número.

La entrada es a través de STDIN; Como dos comandos se leen secuencialmente, debe enviar EOF(Ctrl-D) dos veces, entre las cadenas y al final. Sobrescribe el archivo 1, si está presente.


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

Pruébalo en línea .

Esto funciona de la siguiente manera:

  1. Convierte las cadenas en minúsculas.
  2. Encuentra los caracteres únicos de las dos cadenas juntas. Es decir, determina todos los caracteres que aparecen en las cadenas.
  3. Calcula el histograma de cada cadena. Es decir, para cada cadena encuentra cuántas veces aparece cada uno de los caracteres obtenidos en el paso 2.
  4. Resta los histogramas y toma el valor absoluto de las diferencias. Esto representa cuántas veces aparece un carácter en una cadena más que en la otra.
  5. El resultado es la suma de esas diferencias absolutas.

Esto parece demasiado largo, ¿estás seguro de que es óptimo?
lirtosiast

@ThomasKwa No, para nada :-)
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)

Explicacion :

  1. Cuente la cantidad de veces que cada carácter (en minúsculas) aparece en ay por bseparado.
  2. Agrupe los recuentos por su carácter común.
  3. Reduzca cada grupo con el -operador, que tiene el siguiente efecto:

    • Si solo se encuentra un valor (es decir, el carácter apareció en una sola entrada), se devuelve ese valor.
    • Si se encuentran dos valores (es decir, el carácter apareció en ambas entradas) reste el segundo valor del primero.
  4. Suma el valor absoluto de los valores del paso anterior.


0

Scala , 134 81 bytes

Gracias @ ASCII-only por su trabajo.

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

Pruébalo en línea!




ew, me perdí eso, tengo cosas que aprender en scalagolf
V. Courtois

Jaja, probablemente tengo más cosas que aprender. El primero es Scala: P
solo ASCII el

Sin embargo, esos trucos eran buenos.
V. Courtois
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.