Понедельник Мини-Гольф №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-минутным поиском.


Описание задачи как «написать программу […], которая [делает вещи], используя следующую логику», чтобы позже добавить «Вам не нужно использовать этот точный алгоритм […]», немного противоречиво.
Эдуард

@ Эдуард Правда; Спасибо что подметил это. Я считаю, что теперь лучше.
ETHproductions

Это уже вторник снова. ;)
Мартин Эндер

@ MartinBüttner Трудно написать задачу, пока ты в дороге без Wi-Fi. ;) Не волнуйся, скоро у меня будет новый.
ETHproductions

Ответы:


14

Pyth, 12 байт

ls.-M.prR0.z

Тестирование

Рассматриваемая операция эквивалентна суммирующему оператору вычитания Пита, .-применяемому в обоих направлениях. Вы могли бы назвать это bagwise 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 Спасибо! : D Я сделал тестовый набор сам, на самом деле. Проверьте мой мета пост!
января

Я + 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

Я должен был бы сократить обе строки (или upcase, что эквивалентно.)
гистократ

Ах, конечно. (Хотя мне кажется, что это все равно сэкономит вам пару байт.)
Восстановите Monica iamnotmaynard

4

Python, 90 87 81 80 79 байт

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

Python <3.5 версия, 80 байт

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

объяснение

Для каждого символа в a или b подсчитайте количество вхождений в каждой строке и добавьте (положительную) разницу.

Редактирование: Перечитайте правила, реализованы анонимные функции, улучшен ответ, избавившись от raw_input. Первый гольф, пожалуйста, будьте нежны!

Спасибо sp3000 за улучшение переопределения str.lower и за то, что я понял, что печатать не нужно. Также пробелы. Все еще учусь.

Используя python> = 3.5, существует более короткий способ определения наборов, поэтому байт можно сохранить в предыдущих версиях.


3

Сетчатка, 40 20 байт

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 байт. Единственное отличие состоит в том, что в качестве значения флага вместо -1 используется 255, поскольку при попытке печати происходит 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 байт

Использует массив для хранения счетчика каждого символа в первой строке, минус счетчик во второй строке. Далее он находит сумму абсолютных значений элементов массива: это расстояние.

Golfed:

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

1

PowerShell, 79 байт

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

Почти тот же код, что и мой ответ на Anagram Code Golf ... но ... Я получаю странное поведение, если просто отрываю -eq0от этого ответа, поэтому я вынужден был явно .ToLower()и переписать вне paramдекларации. +

Объяснение также (в основном) скопировано из этого ответа - берет два строковых ввода, делает их строчными, и повторно преобразует их как массивы символов. diffФункция (псевдоним Compare-Object) принимает два массива и возвращает элементы, которые отличаются между ними. Мы используем это путем повторного приведения возврата в виде массива с (), а затем проверки его длины.

+ Например, я получал фиктивные результаты 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

Matlab, 91 байт

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

Попробуйте онлайн .

Это работает следующим образом:

  1. Преобразует строки в нижний регистр.
  2. Находит уникальных персонажей двух строк вместе. То есть определяет все символы, которые когда-либо появляются в строках.
  3. Вычисляет гистограмму каждой строки. То есть для каждой строки определяет, сколько раз появляется каждый из символов, полученных на шаге 2.
  4. Вычитает гистограммы и принимает абсолютные значения разностей. Это показывает, сколько раз символ появляется в одной строке больше, чем в другой.
  5. Результатом является сумма этих абсолютных различий.

Это кажется слишком длинным - ты уверен, что это оптимально?
Lirtosiast

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

Попробуйте онлайн!




я пропустил это, у меня есть чему поучиться у скалагольфа
В. Куртуа

Хаха, у меня, наверное, есть чему поучиться. Первый из них - Scala: P
только для ASCII

эти трюки были хороши, хотя.
В. Куртуа
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.