Виклик детектора подібності


11

Виклик

Давши два ідентифікаційних запитання, спробуйте з’ясувати, наскільки вони схожі, переглянувши відповіді.

Деталі

Вам дадуть два ідентифікатори запитання для codegolf.stackexchange.com; ви можете припустити, що існують питання щодо обох ідентифікаторів, які не видаляються, але не обов'язково є відкритими. Ви повинні пройти всі відповіді та визначити мінімальну відстань Левенштайна між кодом у відповідях на два запитання (не враховуючи видалених відповідей). Тобто слід порівняти кожну відповідь у питанні 1 з кожною відповіддю у питанні 2 та визначити мінімальну відстань Левенштейна. Щоб знайти код у відповіді, припустімо таку процедуру:

Як знайти фрагмент коду

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

Приклади дійсних та недійсних фрагментів коду (з .пробілом) (розділені тоною рівних знаків)

This is `not a valid code snippet because it is not on its own line`
========================================
This is:
`A valid code snippet`
========================================
This is
....not a valid code snippet because there's no spacing line above
========================================
This is

....A valid code snippet because there's a spacing line above
========================================
....Valid code snippet because there's no other text
========================================

Якщо у відповіді немає дійсних фрагментів коду, ігноруйте відповідь повністю. Зауважте, що вам слід брати лише перший блок-код.

Заключні характеристики

Два ідентифікаційних запитання можна ввести у будь-якому розумному форматі для двох цілих чисел. Вихід повинен бути найменшою відстані Левенштейна між будь-якими двома дійсними відповідями з будь-якого завдання. Якщо немає «достовірних» відповідей на один або обидва виклики, виведіть -1.

Тестовий випадок

Для викликів 115715(Вбудовані шестикутники) та 116616(Вбудовані трикутники) обох товариша СпарклПоні, два відповіді Вугілля (обидва - КрітіксіЛітос) мали відстань Левенштейна в 23, що було найменшим. Таким чином, ваш результат для 115715, 116616буде23 .

Редагувати

Ви можете припустити, що запитання має максимум 100 відповідей через обмеження кількості сторінок API. Не слід ігнорувати зворотні посилання в блоках коду, лише якщо сам код коду створений за допомогою зворотних посилань, а не в його власному рядку.

Редагувати

Я достроково припинив період виграшів, тому що я подав прохання моді отримати однотижневу призупинення, і я не хотів, щоб винагорода була автоматично присуджена найвищою оцінкою (що трапляється найдовше). Якщо надходить нове подання або подання вистачає на гольф, щоб стати коротшим, ніж 532 байти до фактичного закінчення періоду виграшів (UTC 00:00 1 червня), я дам цьому виграшу, щоб залишитися вірним моїм обіцянкам, після термін дії суспензії закінчується. Якщо я правильно пам’ятаю, наступного разу мені потрібно подвоїти період щедрості, тому якщо ви отримаєте відповідь, ви можете отримати +200 :)


1
Мене бентежить те, що вважається дійсним фрагментом коду. Чому б не все, що знаходиться в тегах <code> в html?
Захоплення Кальвіна

@HelkaHomba Що з обмеженнями на новий рядок? Я міг би спробувати знайти інший спосіб їх включення.
HyperNeutrino

@HelkaHomba По суті, якщо відповідь містить код з обмеженим зворотом у рядку, його слід ігнорувати.
HyperNeutrino

Це одна з таких відповідей, де простіше зробити основну частину питання. Завантажити сторінку та витягнути кодові блоки складніше, ніж пройти відстань Левенштейна.
Балінт

1
Класно. Просто перевіряю.
Метт

Відповіді:


1

PowerShell, 532 байт

$1,$2=$args
$a={irm "api.stackexchange.com/2.2/questions/$args/answers?pagesize=100&site=codegolf&filter=!9YdnSMKKT"|% i*}
$r={$args.body-replace"(?sm).*?^(<pre.*?>)?<code>(.*?)</code>.*",'$2'}
$1=&$a $1;$2=&$a $2
(0..($1.count-1)|%{
    $c=&$r $1[$_]
    0..($2.count-1)|%{
        &{$c,$d=$args;$e,$f=$c,$d|% le*;$m=[object[,]]::new($f+1,$e+1);0..$e|%{$m[0,$_]=$_};0..$f|%{$m[$_,0]=$_};1..$e|%{$i=$_;1..$f|%{$m[$_,$i]=(($m[($_-1),$i]+1),($m[$_,($i-1)]+1),($m[($_-1),($i-1)]+((1,0)[($c[($i-1)]-eq$d[($_-1)])]))|sort)[0]}};$m[$f,$e]} $c $d
    }
}|sort)[0]

Я залишив там нові рядки для деякої читабельності. Вони все ще відображені в моїй кількості байтів.

Досить впевнений, що в мене є ручка щодо цього. Напруга для мене була фактично здобуття відстані Левенштейна, оскільки PowerShell не має вбудованого для цього, наскільки я знаю. Через це я зміг відповісти на пов'язаний виклик на відстані Левенштейна . Коли мій код посилається на анонімну функцію для LD, ви можете звернутися до цієї відповіді для більш детального пояснення, як це працює.

Код з коментарями та індикатором прогресу

Код може бути реально повільним (через LD), тому я вбудував у себе деякі показники прогресу, щоб я міг слідкувати за діями, коли він розгортався, і не припускати, що він десь застряг у циклі. Код для моніторингу прогресу не знаходиться у верхньому блоці і не зараховується до моєї кількості байтів.

# Assign the two integers into two variables. 
$1,$2=$args

# Quick function to download up to 100 of the answer object to a given question using the SE API
$a={irm "api.stackexchange.com/2.2/questions/$args/answers?pagesize=100&site=codegolf&filter=!9YdnSMKKT"|% i*}

# Quick function that takes the body (as HTML) of an answer and parses out the likely codeblock from it. 
$r={$args.body-replace"(?sm).*?^(<pre.*?>)?<code>(.*?)</code>.*",'$2'}

# Get the array of answers from the two questions linked.
$1=&$a $1;$2=&$a $2

# Hash table of parameters used for Write-Progress
# LD calcuations can be really slow on larger strings so I used this for testing so I knew 
# how much longer I needed to wait.
$parentProgressParameters = @{
    ID = 1 
    Activity = "Get LD of all questions" 
    Status = "Counting poppy seeds on the bagel"
}

$childProgressParameters = @{
    ID = 2
    ParentID = 1
    Status = "Progress"
}


# Cycle each code block from each answer against each answer in the other question.
(0..($1.count-1)|%{
    # Get the code block from this answer
    $c=&$r $1[$_]

    # Next line just for displaying progress. Not part of code. 
    Write-Progress @parentProgressParameters -PercentComplete (($_+1) / $1.count * 100) -CurrentOperation "Answer $($_+1) from question 1"

    0..($2.count-1)|%{
        # Get the code block from this answer   
        $d=&$r $2[$_]

        # Next two lines are for progress display. Not part of code. 
        $childProgressParameters.Activity = "Comparing answer $($_+1) of $($2.count)"
        Write-Progress @childProgressParameters -PercentComplete (($_+1) / $2.count * 100) -CurrentOperation "Answer $($_+1) from question 2"

        # Anonymous function to calculate Levenstien Distance
        # Get a better look at that function here: https://codegolf.stackexchange.com/a/123389/52023
        &{$c,$d=$args;$e,$f=$c,$d|% le*;$m=[object[,]]::new($f+1,$e+1);0..$e|%{$m[0,$_]=$_};0..$f|%{$m[$_,0]=$_};1..$e|%{$i=$_;1..$f|%{$m[$_,$i]=(($m[($_-1),$i]+1),($m[$_,($i-1)]+1),($m[($_-1),($i-1)]+((1,0)[($c[($i-1)]-eq$d[($_-1)])]))|sort)[0]}};$m[$f,$e]} $c $d
    }
# Collect results and sort leaving the smallest number on top.
}|sort)[0]

Моя логіка пошуку блоків коду полягає в тому, щоб приймати відповідь як HTML і шукати набір тегів коду, необов'язково оточений набором попереднього тегу, який починається з власного рядка. Під час тестування він знайшов усі правильні дані про 6 різних наборах питань.

Я намагався працювати з кодом розмітки, але було важко знайти правильний блок коду.

Проба працює

Challenge-Similarity-Detector 97752 122740
57

Challenge-Similarity-Detector 115715 116616
23

Я витратив більшу частину 3 днів на це. Це завдання входить до моїх топ-5 для найбільш веселих спроб. TFTC (спасибі за виклик)
Метт

Хороша робота! Дякую, я радий, що вам сподобалось! :)
HyperNeutrino

Примітка. Я нагородив нагороду раніше, ніж заявлено, тому що я прошу припинити дію, тому не можу пізніше присудити її. Хороша робота! :)
HyperNeutrino

Запит на призупинення?
Метт

Так, я попросив Денніса дати мені відмову на тиждень, щоб я міг зосередитися на шкільній роботі. Це було зроблено раніше (хоча я все ще тут ... я не знаю, коли я зникну).
HyperNeutrino

3

Java + Jsoup, 1027 байт

Перші два аргументи - це ідентифікатори питання.

Гольф:

import org.jsoup.*;import org.jsoup.nodes.*;class M{String a1[]=new String[100],a2[]=new String[100],c[];int i1=0,i2=0;public static void main(String a[])throws Exception{String r="/codegolf/";M m=new M();m.c=m.a1;m.r(Jsoup.connect(r+a[0]).get());m.c=m.a2;m.r(Jsoup.connect(r+a[1]).get());int s=m.ld(m.a1[1],m.a2[1]);for(int i=2;i<m.a1.length;i++)for(int j=2;j<m.a2.length;i++){if(m.a1[i]==null)break;int d=m.ld(m.a1[i],m.a2[j]);if(d<s)s=d;}System.out.print(s);}void r(Document d){a:for(Element e:d.select("td")){for(Element p:e.select("pre")){ a(p.select("code").get(0).html());continue a;}}}void a(String d){c[c==a1?i1++:i2++]=d;}int ld(String a,String b){a=a.toLowerCase();b=b.toLowerCase();int[]costs=new int[b.length()+1];for(int j=0;j<costs.length;j++)costs[j]=j;for(int i=1;i<=a.length();i++){costs[0]=i;int nw=i-1;for(int j=1;j<=b.length();j++){int cj=Math.min(1+Math.min(costs[j],costs[j-1]),a.charAt(i-1)==b.charAt(j-1)?nw:nw+1);nw=costs[j];costs[j]=cj;}}return costs[b.length()];}}

Читає:

import org.jsoup.*;import org.jsoup.nodes.*;

class M {
    String a1[]=new String[100],a2[]=new String[100],c[];
    int i1=0,i2=0;
    public static void main(String a[])throws Exception{
    String r="/codegolf/";
    M m=new M();

    m.c=m.a1;
    m.r(Jsoup.connect(r+a[0]).get());
    m.c=m.a2;
    m.r(Jsoup.connect(r+a[1]).get());

    int s=m.ld(m.a1[1],m.a2[1]);
    for(int i=2;i<m.a1.length;i++)for(int j=2;j<m.a2.length;i++){if(m.a1[i]==null)break;int d=m.ld(m.a1[i],m.a2[j]);if(d<s)s=d;}
    System.out.print(s);
}

void r(Document d) {
    a:for(Element e:d.select("td")) {for(Element p:e.select("pre")) { 
        a(p.select("code").get(0).html());
        continue a;
    }}
}

void a(String d){c[c==a1?i1++:i2++]=d;}

int ld(String a, String b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    int [] costs = new int [b.length() + 1];
    for (int j = 0; j < costs.length; j++)costs[j] = j;
    for (int i = 1; i <= a.length(); i++) {
        costs[0] = i;
        int nw = i - 1;
        for (int j = 1; j <= b.length(); j++) {
            int cj = Math.min(1 + Math.min(costs[j], costs[j - 1]), a.charAt(i - 1) == b.charAt(j - 1) ? nw : nw + 1);
            nw = costs[j];
            costs[j] = cj;
        }
    }
    return costs[b.length()];
}

}


бийте мене до цього !!!! Приємно!
тускіоми

1
Ласкаво просимо до PPCG! Це не проти правил використання сторонніх бібліотек, але ми вимагаємо, щоб використання бібліотеки відзначалося мовою (тому відповідь Java, яка використовує бібліотеку під назвою JavaHTML, позначатиметься "Java + JavaHTML").
Мего

Добре, дякую! Я буду мати це на увазі наступного разу!
Tomahawk2001913

Ніщо не заважає вам використовувати бібліотеку в цьому виклику, якби ви цього хотіли.
Метт

Можливо, мені доведеться зараз, коли хтось довершив мою відповідь!
Tomahawk2001913

0

Математика, 540 байт

f=Flatten;l=Length;P=StringPosition;(H[r_]:=Block[{s,a,t,k},t={};d=1;k="/codegolf/"<>r;s=First/@P[Import[k,"Text"],"<pre><code>"];a=f[First/@P[Import[k,"Text"],"answerCount"]][[1]];While[d<l@s,If[s[[d]]>a,AppendTo[t,s[[d]]]];d++];Table[StringDelete[StringCases[StringTake[Import[k,"Text"],{t[[i]],t[[i]]+200}],"<pre><code>"~~__~~"</code></pre>"],{"<pre><code>","</code></pre>"}],{i, l@t}]];Min@DeleteCases[f@Table[EditDistance[ToString@Row@H[#1][[i]],ToString@Row@H[#2][[j]]],{i,l@H[#1]},{j,l@H[#1]}],0])&


вхід

["115715", "116616"]

вихід

23

використовує вбудований EditDistance, який "дає відстань для редагування або Левенштейна між рядками або векторами u і v."

Щодо математичного тесту

EditDistance["FN«AX²ιβ×__β↓↘β←↙β↑←×__β↖β→↗β","NαWα«X²ι↙AX²⁻ι¹β↙β↑↖β→A⁻α¹α"]

повертає 23

Я здогадуюсь, я можу пограти трохи більше часу.
Бігає кілька хвилин

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