ท้าทายเครื่องตรวจจับความคล้ายคลึงกัน


11

ท้าทาย

ให้ ID คำถามสองข้อพยายามหาว่าพวกเขามีความคล้ายกันเพียงใดโดยดูที่คำตอบ

รายละเอียด

คุณจะได้รับรหัสสองคำถามสำหรับcodegolf.stackexchange.com; คุณอาจคิดว่ามีคำถามสำหรับรหัสทั้งสองที่ไม่ถูกลบ แต่ไม่จำเป็นต้องเปิด คุณต้องวิ่งผ่านคำตอบทั้งหมดและกำหนดระยะทาง Levenshtein ต่ำสุดระหว่างรหัสในคำตอบของคำถามทั้งสอง (ไม่รวมคำตอบที่ถูกลบ) นั่นคือคุณควรเปรียบเทียบทุกคำตอบในคำถาม 1 กับทุกคำตอบในคำถาม 2 และกำหนดระยะทาง Levenshtein ขั้นต่ำ หากต้องการค้นหารหัสในคำตอบให้สมมติขั้นตอนต่อไปนี้:

วิธีค้นหาข้อมูลโค้ด

เนื้อความของข้อความเป็นรหัสที่แท้จริงของคำตอบถ้ามันอยู่ใน backticks และอยู่ในบรรทัดของตัวเองหรือถ้ามันเยื้องกับ 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
========================================

หากไม่มีตัวอย่างข้อมูลที่ถูกต้องในคำตอบให้ละเว้นคำตอบโดยสมบูรณ์ โปรดทราบว่าคุณควรใช้ codeblock แรกเท่านั้น

รายละเอียดสุดท้าย

สามารถป้อน ID คำถามทั้งสองในรูปแบบที่เหมาะสมสำหรับจำนวนเต็ม 2 ตัว ผลลัพธ์ควรเป็นระยะทางที่เล็กที่สุดของ Levenshtein ระหว่างคำตอบที่ถูกต้องสองข้อจากความท้าทายใด ๆ หากไม่มีคำตอบ "ถูกต้อง" -1สำหรับหนึ่งหรือทั้งสองของความท้าทายที่เอาท์พุท

กรณีทดสอบ

สำหรับความท้าทาย115715(สมองกลฝังตัวหกเหลี่ยม) และ116616(สมองกลฝังตัวแบบสามเหลี่ยม) ทั้งสองโดย Comrade SparklePony คำตอบของถ่านสองคำ (ทั้งสองโดย KritixiLithos) มีระยะทางของ Levenshtein เท่ากับ 23 ซึ่งน้อยที่สุด ดังนั้นสำหรับการส่งออกของคุณจะ115715, 11661623

แก้ไข

คุณอาจคิดว่าคำถามมีคำตอบได้ไม่เกิน 100 คำตอบเนื่องจากข้อ จำกัด ในการกำหนดขนาดหน้า API คุณไม่ควรเพิกเฉย backticks ในบล็อครหัสเฉพาะเมื่อ block code นั้นถูกสร้างขึ้นโดยใช้ backticks และไม่อยู่ในบรรทัดของมันเอง

แก้ไข

ฉันยุติช่วงเวลาของรางวัลตั้งแต่เนิ่น ๆ เพราะฉันขอโมดิฟที่จะได้รับการระงับหนึ่งสัปดาห์และฉันไม่ต้องการให้รางวัลจะได้รับรางวัลโดยอัตโนมัติสำหรับคำตอบให้คะแนนสูงสุด (ซึ่งเกิดขึ้นนานที่สุด) หากมีการส่งใหม่เข้ามาหรือมีการตีกอล์ฟมากพอที่จะสั้นกว่า 532 ไบต์ก่อนสิ้นสุดระยะเวลาการจ่ายเงินจริง (UTC 00:00 วันที่ 1 มิถุนายน) ฉันจะให้เงินรางวัลนั้นจริงต่อสัญญาของฉันหลังจากนั้น การระงับจะหมดอายุ ถ้าฉันจำได้อย่างถูกต้องฉันจะต้องเพิ่มระยะเวลาเงินรางวัลเป็นสองเท่าในครั้งต่อไปดังนั้นหากคุณได้รับคำตอบคุณอาจได้รับ +200 :)


1
ฉันสับสนกับสิ่งที่นับว่าเป็นข้อมูลรหัสที่ถูกต้อง ทำไมไม่ใช้แท็ก <code> ใน html
งานอดิเรกของ Calvin

@HelkaHomba แล้วข้อ จำกัด ของบรรทัดใหม่คืออะไร ฉันพยายามหาวิธีอื่นเพื่อรวมสิ่งเหล่านั้น
HyperNeutrino

@HelkaHomba เป็นหลักหากคำตอบมีรหัส backtick- คั่นภายในบรรทัดก็ควรจะละเว้น
HyperNeutrino

นี่เป็นหนึ่งในคำตอบที่ง่ายต่อการทำส่วนหลักของคำถาม การดาวน์โหลดหน้าและแตกบล็อกโค้ดนั้นยากกว่าการทำระยะทางเลเวนเทน
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]

ฉันทิ้งบรรทัดใหม่ไว้ที่นั่นเพื่อให้อ่านง่ายขึ้น ยังคงสะท้อนให้เห็นในการนับไบต์ของฉัน

ค่อนข้างแน่ใจว่าฉันมีที่จับในเรื่องนี้ ส่วนที่ยากสำหรับฉันคือการได้รับระยะทางจาก Levenshtein เนื่องจาก PowerShell ไม่มี builtin สำหรับสิ่งนั้นเท่าที่ฉันรู้ เพราะการที่ผมสามารถที่จะตอบความท้าทายที่เกี่ยวข้องบน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 ชุดที่แตกต่างกัน

ฉันพยายามทำงานจากรหัส markdown แต่มันยากเกินไปที่จะค้นหาบล็อคโค้ดที่ถูกต้อง

ตัวอย่างการวิ่ง

Challenge-Similarity-Detector 97752 122740
57

Challenge-Similarity-Detector 115715 116616
23

ฉันใช้เวลาส่วนที่ดีกว่านี้ใน 3 วันเพื่อดูสิ่งนี้ ความท้าทายนี้อยู่ใน 5 อันดับแรกของฉันสำหรับการทดลองที่สนุกที่สุด TFTC (ขอบคุณสำหรับการท้าทาย)
แมตต์

งานที่ดี! ขอบคุณฉันดีใจที่คุณสนุก! :)
HyperNeutrino

หมายเหตุ: ฉันได้รับรางวัลเร็วกว่าที่ระบุไว้เนื่องจากฉันขอการระงับดังนั้นฉันจึงไม่สามารถให้รางวัลได้ในภายหลัง เยี่ยมมาก! :)
HyperNeutrino

ร้องขอการระงับหรือไม่
Matt

ใช่ฉันขอให้เดนนิสให้ฉันพักหนึ่งสัปดาห์เพื่อให้ฉันสามารถมุ่งเน้นไปที่การเรียน มันทำมาก่อน (แม้ว่าฉันจะยังอยู่ที่นี่ ... ฉันไม่รู้ว่าจะหายไปเมื่อไหร่)
HyperNeutrino

3

Java + Jsoup, 1,027 ไบต์

อาร์กิวเมนต์สองข้อแรกคือรหัสคำถาม

แข็งแรงเล่นกอล์ฟ:

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 + JavaHTML")
Mego

โอเคขอบคุณ! ฉันจะจำไว้ว่าในครั้งต่อไป!
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 ในตัวซึ่ง "ให้การแก้ไขหรือ Levenshtein ระยะห่างระหว่างสตริงหรือเวกเตอร์ u และ v"

สำหรับกรณีทดสอบทางคณิตศาสตร์

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

ส่งคืน 23

ฉันคิดว่าฉันสามารถเล่นกอล์ฟได้อีก
สักครู่เพื่อวิ่ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.