Monday Mini-Golf # 3: Anagram distance

24

Monday Mini-Golf: Seria krótkich wyzwań, opublikowanych (miejmy nadzieję!) W każdy poniedziałek.
(Przepraszam, ten jest trochę spóźniony.)

Jestem pewien, że większość z was słyszała o odległości Levenshteina , algorytmie do obliczania odległości między dwoma łańcuchami. To wyzwanie polega na wdrożeniu podobnego algorytmu mojego wynalazku *, zwanego odległością anagramową . Główna różnica polega na tym, że kolejność znaków nie ma znaczenia; zamiast tego mierzone są tylko znaki unikalne dla jednego lub drugiego łańcucha.

Wyzwanie

Celem wyzwania jest napisanie programu lub funkcji, która przyjmuje dwa ciągi znaków i zwraca odległość między nimi anagramów. Głównym sposobem na to jest użycie następującej logiki:

  1. Konwertuj oba ciągi znaków na małe i (opcjonalnie) sortuj znaki każdego z nich alfabetycznie.
  2. Chociaż ciągi zawierają co najmniej jeden taki sam znak, usuń pierwsze wystąpienie tego znaku z każdego ciągu.
  3. Dodaj długości pozostałych ciągów i zwróć / wyślij wynik.

Przykład

Jeśli dane wejściowe to:

Hello, world!
Code golf!

Następnie, małe i posortowane, stają się: (według domyślnego sortowania JS; zwróć uwagę na spacje wiodące)

 !,dehllloorw
 !cdefgloo

Usuwając wszystkie znaki z obu ciągów, otrzymujemy:

,hllrw
cfg

Zatem odległość anagramu między oryginalnymi dwoma łańcuchami = 6 + 3 = 9.

Detale

  • Ciągi mogą być pobierane w dowolnym rozsądnym formacie.
  • Ciągi będą składały się wyłącznie z drukowalnego ASCII.
  • Same łańcuchy nie będą zawierać żadnych białych znaków oprócz zwykłych spacji. (Bez kart, nowych linii itp.)
  • Nie musisz używać tego dokładnego algorytmu, o ile wyniki są takie same.

Przypadki testowe

Wejście 1:

Hello, world!
Code golf!

Wyjście 1:

9

Wejście 2:

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

Wyjście 2:

0

Wejście 3:

All unique characters here!
Bdfgjkmopvwxyz?

Wyjście 3:

42

Wejście 4:

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

Wyjście 4:

30

Wejście 5:

all lowercase.
ALL UPPERCASE!

Wyjście 5:

8

Punktacja

To jest , więc wygrywa najkrótszy prawidłowy kod w bajtach. Tiebreaker przechodzi do przesyłania, które jako pierwsze osiągnęło końcową liczbę bajtów. Zwycięzca zostanie wybrany w następny poniedziałek, 12 października. Powodzenia!

Edycja: Gratulacje dla zwycięzcy, @isaacg, używając Pytha (ponownie) dla zadziwiającego 12 bajtów!

* Jeśli ten algorytm był używany gdzie indziej i / lub otrzymał inną nazwę, daj mi znać! Nie udało mi się go znaleźć podczas 20-minutowego wyszukiwania.

ETHprodukcje
źródło
Opisanie zadania jako „napisz program […], który [robi rzeczy] przy użyciu następującej logiki”, aby później dodać „Nie musisz używać tego dokładnego algorytmu […]”, jest trochę sprzeczne.
Édouard,
@ Édouard True; dzięki za zwrócenie na to uwagi. Wierzę, że teraz jest lepiej.
ETHproductions
Znowu jest już wtorek. ;)
Martin Ender
@ MartinBüttner Trudno jest napisać wyzwanie, gdy jesteś w drodze bez Wi-Fi. ;) Nie martw się, za chwilę przygotuję nowy.
ETHprodukcje

Odpowiedzi:

14

Pyth, 12 bajtów

ls.-M.prR0.z

Zestaw testowy

Operacja, o której mowa, jest równoważna z operatorem odejmowania bajtowego Pytha .-, stosowanym w obu kierunkach. Przypuszczam, że można to nazwać bag bag xor.

Rozwiązaniem jest:

.z: pobierz dane jako listę 2 ciągów.

rR0: konwertuj oba na małe litery.

.p: Tworzy wszystkie permutacje, tzn. Normalne i odwrócone.

.-M: Zamapuj .-operację dla każdego zamówienia.

s: Połącz wyniki.

l: Wydrukuj długość.

isaacg
źródło
Pomyślałem, że wszystkie odpowiedzi mogą być zbyt długie… Dobra robota!
ETHprodukcje
8

JavaScript (ES7), 92 bajty

Definiuje anonimową funkcję.

Aby przetestować, uruchom poniższy fragment kodu. Możesz edytować kod i kliknąć „Test”, aby porównać jego wyniki z oryginałem. (Zostaw komentarz, jeśli znajdziesz poprawę!) Dane wejściowe są jak "Hello, world!", "Code golf!"w polu wprowadzania.

Dzięki @ETHproductions za oszczędność 6 bajtów!


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

Więcej informacji o pakiecie testowym


Jak to działa

//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
źródło
Pracowałem nad macierzą ES6 przez godzinę i udało mi się sprowadzić ją do 122. Wygląda na to, że patrzyłem w złym kierunku! +1
ETHprodukcje
BTW, można wymienić .join("")+bz .join``+bbez skutku.
ETHproductions
1
Wow, skąd masz ten zestaw testowy? To znakomicie! Chciałbym móc dać +1 jeszcze trzy lub cztery razy ...
ETHprodukcje
@ETHproductions Dziękujemy! : Właściwie to DI sam stworzyłem zestaw testowy. Sprawdź mój meta post!
jrich,
Dałem +1, mam nadzieję, że zrekompensuje to, że nie mogę tu +5. ;)
ETHproductions
6

CJam, 23 19 bajtów

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

Wypróbuj online w interpretatorze CJam .

Jak to działa

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
źródło
4

Ruby, 62

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

Musi być lepszy sposób.

Edytuj: 57 znaków dzięki iamnotmaynard badającej ścieżkę, na którą byłem zbyt leniwy.

#!ruby -naF|
gets.upcase!
p$F.count{|c|!$_.sub!(c.upcase){}}+~/$/
histocrat
źródło
submoże brać sznurki. Nie możesz użyć c.downcasezamiast /#{Regexp.escape c}/i?
Przywróć Monikę iamnotmaynard
Musiałbym zapisać oba ciągi (lub upcase, równoważnie.)
histocrat
Ach, oczywiście. (Chociaż wydaje mi się, że zrobienie tego nadal zaoszczędziłoby ci kilka bajtów.)
Przywróć Monikę iamnotmaynard
4

Python, 90 87 81 80 79 bajtów

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

Wersja Python <3.5, 80 bajtów

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

Wyjaśnienie

Dla każdego znaku a lub b policz liczbę wystąpień w każdym ciągu i dodaj różnicę (dodatnią).

Edycja: Ponowne czytanie reguł, akceptowane anonimowe funkcje są akceptowane, poprawiona odpowiedź poprzez pozbycie się raw_input. Najpierw golf, proszę bądź delikatny!

Dzięki sp3000 za ulepszenie redefinicji str. Niższej i uświadomienie mi, że druk jest niepotrzebny. Również spacje. Wciąż się uczę.

Przy użyciu python> = 3.5 istnieje krótszy sposób definiowania zestawów, więc bajt można zapisać w stosunku do poprzednich wersji.

Mego
źródło
3

Siatkówka, 40 20 bajtów

20 bajtów zaoszczędzonych dzięki Martinowi Büttnerowi.

Umieść każdą linię we własnym pliku i zamień na \ndosłownie nowy wiersz.

+i`(.)(.*\n.*)\1
$2
.
Numer jeden
źródło
2

pb , 648 bajtów

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

Pobiera dane wejściowe ze znakiem tabulacji oddzielającym dwa ciągi.

Ten był doozy. W rzeczywistości implementacja algorytmu nie była najtrudniejszą częścią, która przyszła stosunkowo łatwo. Ale musiałem zrobić dwie rzeczy, które są trudne do zrobienia w PB: Niewrażliwość na wielkość liter i itoa. Zdarzyło mi się, że program do konwersji na małe litery leżał wokoło (sam 211 bajtów długości) i wszystko inne zostało przypięte do końca, aby wykonać pracę specjalnie dla tego wyzwania.

Ten program można oglądać na YouTube! Jest kilka rzeczy, o których należy pamiętać:

  • Ta wersja programu jest nieco zmodyfikowana, waży 650 bajtów. Jedyną różnicą jest to, że 255 jest używane jako wartość flagi zamiast -1, ponieważ próba drukowania chr(-1)powoduje awarię interpretera podczas działania w trybie zegarka.
  • Dane wejściowe w tym filmie to Hello, world!i Code golf.. Jest to nieco inna niż jedna z przykładowych danych wejściowych w wyzwaniu; Użyłem go, ponieważ był krótki, ale zmodyfikowałem go tak, aby poprawne wyjście wynosiłoby 10 zamiast 9. To tylko, aby pokazać, że liczba jest drukowana poprawnie, nawet jeśli jest to wiele cyfr, co jest trudne w pb.
  • Tłumacz jest okropny i pokazuje to tutaj. W szczególności znak tabulacji usuwa odstępy, więc w przypadku dużych fragmentów filmu rzeczy nie są wyrównane, za każdym razem, gdy bajt jest ustawiony na 10, pokazuje podział wiersza, mimo że język nadal uważa go za jedną „linię”, i fakt, że przesuwa on kursor na początek zamiast czyszczenia ekranu, oznacza, że ​​czasami w filmie jest wiele znaków, których tak naprawdę nie ma, po prostu nigdy nie odeszły, kiedy tam były. Istnieją pewne zabezpieczenia przed tym w pbi, ale faktem jestchr(10)nie jest właściwie traktowany, co czyni je w dużej mierze bezużytecznymi. Biorąc to wszystko pod uwagę, uważam, że oglądanie tego jest prawie piękne. To ogromny bałagan okropnego kodu interpretującego inny okropny kod, jego fragmenty rozkładają się na twoich oczach, a jednak wszystko działa na tyle, aby uzyskać właściwą odpowiedź. Wygląda na to, że śmieci są drukowane, ale jeśli dokładnie obejrzysz ze znajomością źródła, możesz dowiedzieć się, co robi i dlaczego w dowolnym momencie. Kiedy oglądam ten film, czuję się jak Cypher:I... I don’t even see the code. All I see is blonde, brunette, red-head.

Bez zbędnych ceregieli, oto kod niepoznany.

### 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. :)
}
podziemny monorail
źródło
2

C ++ 199 bajtów

Używa tablicy do przechowywania liczby każdego znaku w pierwszym ciągu, pomniejszając liczbę w drugim ciągu. Następnie znajduje się suma wartości bezwzględnych elementów tablicy: jest to odległość.

Gra w golfa:

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

Nie golfowany:

#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
źródło
1

PowerShell, 79 bajtów

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

Prawie dokładnie taki sam kod jak moja odpowiedź na Anagram Code Golf ... ale ... Mam dziwne zachowanie, jeśli po prostu odetnę się -eq0od tej odpowiedzi, więc skończyło się na tym, że muszę jawnie .ToLower()i przekształcić poza paramdeklaracją. +

Wyjaśnienie również (głównie) skopiowane z tej odpowiedzi - pobiera dwa ciągi znaków wejściowych, czyni je małymi literami i ponownie rzutuje je jako tablice znaków. diffFunction (aliasem Compare-Object) wykonuje dwie tablice i zwrotów przedmiotów, które różnią się między nimi. Wykorzystujemy to, ponownie rzutując return jako tablicę (), a następnie sprawdzając jego długość.

+ Na przykład uzyskiwałem fałszywe wyniki param([char[]]$a,[char[]]$b)(diff $a $b).lengthwall lowercase. / ALL UPPERCASE!testu. Gdybym ręcznie rozdzielił tablice (np. Uruchomił (diff ('a','l','l'...), działałby dobrze, ale zawodziłby się za każdym razem, gdy duże / małe litery nakładały się na casting. Wszystko, co mogę przeczytać na temat dokumentacji, diffdomyślnie nie rozróżnia wielkości liter, więc ... wzruszenie ramion ???

AdmBorkBork
źródło
Bardzo dziwne. Nie jest potrzebny w żadnym innym przypadku (nawet z różną rozróżnianiem wielkości liter).
Jonathan Leech-Pepin
1

Bash, 68 67 bajtów

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

ja że to działa. Zwróć uwagę na końcowe spacje w drugim wierszu.

Przypadki testowe

$ ./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
źródło
1

Perl, 52 46 bajtów + 3 przełączniki (a, F, n) = 55 49 bajtów

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

Pobiera dane wejściowe ze STDIN z ciągami wejściowymi w swoich własnych wierszach, zakończonych przez EOF.

Przełączniki:

-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

Kod:

# %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
źródło
1

Narzędzia Bash + GNU, 53

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

sedprzekształca małe litery i dzieli ciąg na linie dla sort. Ponieważ musimy to zrobić dwa razy, nadałem jej funkcję. comm3 -3odfiltrowuje odpowiednie linie i wc -ltworzy liczbę.

Wejście odbywa się za pośrednictwem STDIN; ponieważ dwa polecenia są odczytywane sekwencyjnie, musisz wysłać EOF(Ctrl-D) dwa razy, między łańcuchami i na końcu. Zastępuje plik 1, jeśli jest obecny.

xebtl
źródło
1

Matlab, 91 bajtów

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

Wypróbuj online .

Działa to w następujący sposób:

  1. Konwertuje ciągi znaków na małe litery.
  2. Znajduje unikalne postacie dwóch ciągów razem. Oznacza to, że określa wszystkie znaki, które kiedykolwiek pojawią się w łańcuchach.
  3. Oblicza histogram każdego łańcucha. Oznacza to, że dla każdego łańcucha znajduje się liczba wyświetleń każdego ze znaków uzyskanych w kroku 2.
  4. Odejmuje histogramy i przyjmuje wartość bezwzględną różnic. Reprezentuje to, ile razy znak pojawia się w jednym ciągu więcej niż w drugim.
  5. Wynik jest sumą tych absolutnych różnic.
Luis Mendo
źródło
To wydaje się zbyt długie - czy jesteś pewien, że jest optymalne?
lirtosiast,
@ThomasKwa Nie, wcale nie :-)
Luis Mendo
0

F #, 134 126 bajtów

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)

Objaśnienie :

  1. Policz, ile razy każdy (mały) znak pojawia się w aib oddzielnie.
  2. Pogrupuj liczniki według ich wspólnego charakteru
  3. Zmniejsz każdą grupę za pomocą -operatora, co ma następujący efekt:

    • Jeśli zostanie znaleziona tylko jedna wartość (tzn. Znak pojawi się tylko na jednym wejściu), wartość ta zostanie zwrócona.
    • Jeśli znaleziono dwie wartości (tj. Znak pojawił się na obu wejściach), odejmij drugą wartość od pierwszej.
  4. Zsumuj wartość bezwzględną wartości z poprzedniego kroku.

pswg
źródło
0

Scala , 134 81 bajtów

Dzięki @ ASCII-tylko za ich pracę.

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

Wypróbuj online!

V. Courtois
źródło
81
Tylko
ew, tęskniłem za tym, muszę się uczyć w skalagolfie
V. Courtois
Haha, prawdopodobnie mam więcej rzeczy do nauczenia się. Pierwszym z nich jest Scala: P
tylko ASCII
te sztuczki były jednak miłe.
V. Courtois