Понеділок міні-гольф №3: відстань на Анаграмі


24

Понеділок Міні-Гольф: Серія коротких викликів з , що публікуються (сподіваємось!) Щопонеділка.
(Вибачте, що це трохи пізно.)

Я впевнений, що більшість з вас чули про відстань Левенштейна , алгоритм обчислення відстані між двома струнами. Ну, цей виклик полягає у впровадженні аналогічного алгоритму мого власного винаходу *, який називається відстань анаграми . Основна відмінність полягає в тому, що порядок символів не має значення; натомість вимірюються лише символи, унікальні для однієї або іншої струни.

Виклик

Мета завдання - написати програму або функцію, яка займає два рядки і повертає між ними відстань анаграми. Основний спосіб зробити це - використовувати таку логіку:

  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 переходить до подання, яке першим дійшло до остаточного підрахунку байтів. Переможець буде обраний наступного понеділка, 12 жовтня. Удачі!

Редагувати: Вітаю переможця, @isaacg, використовуючи Pyth (знову) для приголомшливих 12 байт!

* Якщо цей алгоритм був використаний в іншому місці та / або дано інше ім'я, будь ласка, дайте мені знати! Я не зміг його знайти за 20-хвилинний пошук.


Характеризуючи завдання як "написати програму [...], яка [робить речі] за допомогою наступної логіки", щоб згодом додати "Вам не потрібно використовувати цей точний алгоритм [...]", є суперечливим.
Едуард

@ Édouard True; дякую, що вказали на це. Я вірю, що зараз краще.
ETHproductions

Знову вже вівторок. ;)
Мартін Ендер

@ MartinBüttner Як би важко написати виклик, поки ти в дорозі без wi-fi. ;) Не хвилюйся, у мене буде готовий новий трохи.
ETHproductions

Відповіді:


14

Pyth, 12 байт

ls.-M.prR0.z

Тестовий набір

Операція, про яку йде мова, еквівалентна оператору віднімання сумки Pyth .-, застосованому в обох напрямках. Ви можете це назвати сумно xor.

Рішення таке:

.z: отримати введення як список з 2 рядків.

rR0: перетворити обидва в малі регістри.

.p: Формуйте всі перестановки, тобто нормальні та зворотні.

.-M: Позначте .-операцію за кожним замовленням.

s: Об'єднайте результати.

l: Друк довжини.


І я думав, що всі відповіді можуть бути занадто довгими ... Молодці!
ETHproductions

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

До речі, ви могли б замінити .join("")+bз .join``+bбез ефекту.
ETHproductions

1
Вау, де на землі ти взяв цей тестовий набір? Це геніально! Я хотів би, щоб я міг поставити +1 ще три-чотири рази ....
ETHproductions

@ETHproductions Дякую! : Насправді Д.І. склав тестовий набір. Перевірте мій мета-пост!
jrich

Я + 1'е там, сподіваюся, що це компенсує не в змозі +5 тут. ;)
ETHproductions

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

Рубі, 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

4

Пітон, 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 байт

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)Якщо не оброблено належним чином, то тут вони значною мірою марні. За всіма сказаними, я думаю, що це майже якось красиво дивитися. Це величезний хаос жахливого коду, що інтерпретує інший жахливий код, його фрагменти розпадаються перед вашими очима, і все ж все працює достатньо, щоб отримати правильну відповідь. Схоже, що сміття друкується, але якщо ви уважно стежите за знаннями джерела, ви зможете з’ясувати, що це робить і чому в будь-який момент. Я відчуваю себе Сайфер, коли дивлюсь це відео: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декларацією. +

Пояснення також (здебільшого) скопійовано з цієї відповіді - Бере два вхідні рядки, робить їх малими літерами та повторно вводить їх у вигляді масивів char. diffФункція (псевдонім Compare-Object) приймає два масиви і повертає елементи, які відрізняються між ними. Ми використовуємо це шляхом повторного введення повернення у масив (), а потім перевірки його довжини.

+ Наприклад, я отримував фіктивні результати param([char[]]$a,[char[]]$b)(diff $a $b).lengthна all lowercase./ ALL UPPERCASE!test. Якби я вручну відокремив масиви (наприклад, пробіг (diff ('a','l','l'...), він спрацював нормально, але вийшов би з ладу кожного разу, коли було б перекриття капіталу / малого регістру з кастингом. Все, що я можу прочитати в документації, зазначає, що diffце за замовчуванням нечутливе до регістру, тому ... знизуйте плечима ???


Дуже дивно. Він не потрібен для жодного з інших випадків (навіть з різною чутливістю до регістру).
Джонатан Ліч-Пепін

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 утиліти, 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

Матлаб, 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

@ThomasKwa Ні, зовсім не :-)
Луїс Мендо


0

F #, 134 126 байт

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. Підсумуйте абсолютне значення значень попереднього кроку.


0

Scala , 134 81 байт

Дякуємо @ ASCII лише за їх роботу.

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

Спробуйте в Інтернеті!




Так, я пропустив це, мені є чому навчитися у скалагольфа
В. Куртуа

Ха-ха, у мене, мабуть, є чому ще навчитися. Перший - Скала: P
лише для ASCII

ці трюки були приємні, хоча.
В. Куртуа
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.