도전 유사성 검출기


11

도전

두 개의 질문 ID가 주어지면 답을보고 비슷한 지 알아 봅니다.

세부

에 대한 두 개의 질문 ID가 제공됩니다 codegolf.stackexchange.com. 삭제되지 않았지만 반드시 공개되지 않은 두 ID 모두에 대해 질문이 있다고 가정 할 수 있습니다. 모든 답변을 검토하고 두 질문에 대한 답변에서 코드 사이의 최소 Levenshtein 거리를 결정해야합니다 (삭제 된 답변 제외). 즉, 질문 1의 모든 답변을 질문 2의 모든 답변과 비교하고 최소 레 벤슈 테인 거리를 결정해야합니다. 답변에서 코드를 찾으려면 다음 절차를 가정하십시오.

코드 스 니펫을 찾는 방법

텍스트 본문은 백틱으로되어 있고 자체 줄에 있거나 위의 텍스트가 없으면 그 위에 빈 줄이있는 4 개의 공백으로 들여 쓰기 된 경우 답변의 실제 코드입니다.

유효하고 유효하지 않은 코드 스 니펫 ( .공백 포함)의 예 (톤으로 등호로 구분)

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

답변에 유효한 코드 스 니펫이 없으면 답변을 완전히 무시하십시오. 첫 번째 코드 블록 만 사용해야합니다.

최종 사양

두 개의 질문 ID는 2 개의 정수에 대해 적절한 형식으로 입력 할 수 있습니다. 출력은 어느 하나의 챌린지에서 유효한 두 대답 사이의 최소 레 벤슈 테인 거리 여야합니다. 챌린지 중 하나 또는 둘 다에 대한 "올바른"답변이없는 경우 output -1.

테스트 사례

SparklePony 동지의 챌린지 115715(Embedded Hexagons)와 116616(Embedded Triangles)의 경우, 두 Charcoal 답변 (KritixiLithos)은 레 벤슈 테인 거리가 23으로 가장 작았습니다. 따라서에 대한 출력은 115715, 116616입니다 23.

편집하다

API 페이지 크기 제한으로 인해 질문에 최대 100 개의 답변이 있다고 가정 할 수 있습니다. 코드 블록 자체가 자체 행이 아닌 백틱을 사용하여 작성된 경우에만 코드 블록의 백틱을 무시해서는 안됩니다.

편집하다

나는 현상금 기간을 일주일 정학 받기 위해 모드에 요청했고 바운티가 자동으로 최고 점수 답변 (가장 길다)에 수여되기를 원하지 않기 때문에 바운티 기간을 일찍 종료했습니다. 바운티 기간이 실제로 끝나기 전에 (6 월 1 일 UTC 00:00) 새로운 제출물이 들어 오거나 제출물이 골프장 532 바이트보다 짧아 질 경우, 그 약속을 지키기 위해 바운티를 줄 것입니다. 정지가 만료됩니다. 올바르게 기억한다면 다음에 현상금 기간을 두 배로 늘려야하므로 답변을 받으면 +200을 얻을 수 있습니다. :)


1
유효한 코드 스 니펫으로 간주되는 것이 혼란 스럽습니다. 왜 HTML의 <code> 태그에 무엇이 있습니까?
Calvin 's Hobbies

@HelkaHomba 줄 바꿈 제한은 어떻습니까? 나는 그것들을 통합하는 다른 방법을 찾으려고 노력할 수 있습니다.
HyperNeutrino

@HelkaHomba 기본적으로, 답변에 한 줄 내에 백틱으로 구분 된 코드가 포함되어 있으면 무시해야합니다.
HyperNeutrino

이것은 질문의 주요 부분을 수행하는 것이 더 쉬운 답변 중 하나입니다. 페이지를 다운로드하고 코드 블록을 추출하는 것은 levenshtein 거리를 수행하는 것보다 어렵습니다.
Bálint

1
멋있는. 그냥 확인 중입니다.
Matt

답변:


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에는 내가 아는 한 내장 기능이 없기 때문에 실제로 Levenshtein 거리를 얻는 것이 어려운 부분이었습니다. 그것 때문에 나는 Levenshtein 거리 에 관한 도전에 대답 할 수 있었다 . 내 코드가 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 (감사합니다)
Matt

좋은 작업! 고마워요, 기뻐요! :)
HyperNeutrino

참고 : 정지를 요청하고 있기 때문에 바운티를 이전보다 먼저 수여하여 나중에 상을 수여 할 수 없습니다. 잘 했어! :)
HyperNeutrino

정학 요청?
Matt

예, 저는 Dennis에게 1 주 정학을 요청하여 학업에 집중할 수 있도록했습니다. 그것은 전에 이루어졌습니다 (여전히 여기 있지만 ... 나는 언제 사라질지 모르겠습니다).
HyperNeutrino

3

Java + Jsoup, 1027 바이트

처음 두 인수는 질문 ID입니다.

골프 :

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()];
}

}


나를 이길 !!!! 좋은!
tuskiomi

1
PPCG에 오신 것을 환영합니다! 타사 라이브러리를 사용하는 규칙에 위배되지는 않지만 라이브러리 사용은 언어로 표시해야합니다 (따라서 JavaHTML이라는 라이브러리를 사용하는 Java 응답에는 "Java + JavaHTML"이라는 레이블이 지정됨).
Mego 2016 년

알았어 고마워! 다음에 염두에 두겠습니다!
Tomahawk2001913

원한다면이 챌린지에서 라이브러리 사용을 막을 수있는 것은 없습니다.
Matt

누군가가 내 대답을 넘어 섰을 수도 있습니다.
Tomahawk2001913

0

Mathematica, 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 사이의 편집 또는 Levenshtein 거리를 제공합니다."

테스트 케이스 수학

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

23을 반환

나는 조금 더 내가 골프 할 수있는 추측
실행에 몇 분 정도 소요됩니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.