Zorluk Benzerlik Dedektörü


11

Meydan okuma

İki soru kimliği verildiğinde, cevaplara bakarak ne kadar benzer olduklarını anlamaya çalışın.

ayrıntılar

Size iki soru kimliği verilecektir codegolf.stackexchange.com; her iki kimlik için de silinmemiş, ancak mutlaka açık olmayan sorular olduğunu varsayabilirsiniz. Tüm soruları yanıtlamanız ve iki soruya verilen cevaplardaki (silinmiş cevaplar hariç) kod arasındaki minimum Levenshtein mesafesini belirlemeniz gerekir. Yani, 1. sorudaki her cevabı 2. sorudaki her cevapla karşılaştırmalı ve minimum Levenshtein mesafesini belirlemelisiniz. Bir yanıtta kodu bulmak için aşağıdaki yordamı uygulayın:

Kod pasajı nasıl bulunur?

Bir metin gövdesi, geri dönüşlerde ve kendi satırındaysa veya 4 boşlukla girintiliyse, üzerinde metin yoksa, cevabın gerçek kodudur.

Geçerli ve geçerli olmayan kod snippet'lerine ( .boşluk olarak) (bir ton eşittir işaretiyle ayrılmış) örnekleri

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

Yanıtta geçerli bir kod parçacığı yoksa, yanıtı tamamen yok sayın. Yalnızca ilk kod bloğunu almanız gerektiğini unutmayın.

Nihai Özellikler

İki soru kimliği, 2 tamsayı için herhangi bir makul biçimde girilebilir. Çıktı, her iki sınamadan iki geçerli cevap arasındaki en küçük Levenshtein mesafesi olmalıdır. Zorlukların biri veya her ikisi için "geçerli" cevap yoksa çıktı alın -1.

Test durumu

115715SparklePony 116616Yoldaş tarafından hem meydan okuma (Gömülü Altıgenler) hem de (Gömülü Üçgenler) için iki Kömür cevabı (her ikisi de KritixiLithos tarafından) 23'lük bir Levenshtein mesafesine sahipti, bu en küçükti. Böylece, çıktı için 115715, 116616olacaktır 23.

Düzenle

Bir API sayfa boyutu kısıtlaması nedeniyle sorunun en fazla 100 yanıtı olduğunu varsayabilirsiniz. Kod bloklarındaki backtick'leri yok saymamalısınız, yalnızca kod bloğunun kendisi kendi satırında değil backticks kullanılarak oluşturulmuşsa.

Düzenle

Ödül dönemini erken sonlandırdım çünkü bir haftalık askıya almak için bir mod talebinde bulundum ve ödülün otomatik olarak en yüksek puanlama cevabına (en uzun olan) verilmesini istemedim. Yeni bir gönderim gelirse veya bir gönderim, ödül döneminin gerçek sonundan önce (1 Haziran'da UTC 00:00) 532 bayttan daha kısa olacak şekilde golf oynarsa, sözüme sadık kalmak için bir ödül vereceğim. süspansiyonun süresi dolar. Eğer doğru hatırlıyorsam, bir dahaki sefere lütuf dönemini iki katına çıkarmam gerekiyor, bu yüzden cevap alırsan +200 alabilirsin :)


1
Geçerli bir kod snippet'i olarak sayılan şeylerin kafam karıştı. Neden html'deki <code> etiketlerinde ne varsa?
Calvin'in Hobileri

@HelkaHomba Yeni satır kısıtlamalarına ne dersiniz? Bunları birleştirmek için başka bir yol bulmaya çalışabilirdim.
HyperNeutrino

@HelkaHomba Temel olarak, cevap bir satırda backtick ile ayrılmış kod içeriyorsa, yok sayılmalıdır.
HyperNeutrino

Bu, sorunun ana kısmını yapmanın daha kolay olduğu cevaplardan biridir. Sayfayı indirmek ve kod bloklarını çıkarmak, levenshtein mesafesini yapmaktan daha zordur.
Bálint

1
Güzel. Sadece kontrol.
Mat

Yanıtlar:


1

PowerShell, 532 Bayt

$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]

Okunabilirlik için orada yeni satırlar bıraktım. Hala bayt sayımlara yansıyor.

Eminim bu konuda bir sorunum var. PowerShell'in bildiğim kadarıyla bunun için bir yerleşik olmadığı için benim için zor olan kısım Levenshtein mesafesini almaktı. Bu nedenle Levenshtein mesafesindeki ilgili soruna cevap verebildim . Kodum LD için anonim bir işleve başvurduğunda, bunun nasıl çalıştığına dair daha ayrıntılı bir açıklama için bu cevaba başvurabilirsiniz.

Yorum ve ilerleme göstergesi içeren kod

Kod (LD nedeniyle) çok yavaş alabilir, bu yüzden kendim için bazı ilerleme göstergeleri inşa ettim, böylece açıldıkça eylemi takip edebilirim ve bir yerde bir döngüde sıkıştığını varsaymam. İlerlemeyi izleme kodu üst blokta veya bayt sayımda sayılmıyor.

# 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]

Kod bloklarını bulma mantığım HTML olarak yanıt almak ve isteğe bağlı olarak kendi satırında başlayan bir ön etiket kümesi ile çevrelenmiş bir kod etiketi kümesi aramaktır. Test sırasında 6 farklı soru setindeki tüm doğru verileri buldu.

Markdown kodundan çalışmaya çalıştım ama doğru kod bloğunu bulmak çok zordu.

Örnek çalışmalar

Challenge-Similarity-Detector 97752 122740
57

Challenge-Similarity-Detector 115715 116616
23

3 Gün daha iyi parçası bu bakarak geçirdim. Bu meydan okuma en eğlenceli girişim için ilk 5'de. TFTC (Mücadele için teşekkürler)
Matt

İyi iş! Teşekkürler, hoşunuza gittiğine sevindim! :)
HyperNeutrino

Not: Ödülünü belirtilenden daha önce verdim çünkü askıya alınmayı talep ediyorum, bu yüzden daha sonra ödüllendiremiyorum. Aferin! :)
HyperNeutrino

Askıya alma isteği mi istiyorsunuz?
Matt

Evet, Dennis'ten bana okulda odaklanabilmem için 1 haftalık bir erteleme yapmasını istedim. Daha önce yapılmıştı (yine de buradayım ... ne zaman kaybolacağımı bilmiyorum).
HyperNeutrino

3

Java + Jsoup, 1027 bayt

İlk iki argüman soru kimlikleri.

golfed:

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

Okunabilir:

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

}


beni dövdü !!!! Güzel!
tuskiomi

1
PPCG'ye Hoşgeldiniz! Üçüncü taraf bir kitaplık kullanmak kurallara aykırı değildir, ancak kitaplık kullanımının dil ile not edilmesini gerektirir (bu nedenle JavaHTML adlı kitaplığı kullanan bir Java yanıtı "Java + JavaHTML" olarak etiketlenir).
Mego

Tamam teşekkürler! Bunu bir dahaki sefere aklımda tutacağım!
Tomahawk2001913

İsterseniz bu meydan okumada kitaplık kullanmanıza engel olan hiçbir şey yoktur.
Matt

Şimdi birisinin cevabımı atlaması gerekebilir!
Tomahawk2001913

0

Mathematica, 540 bayt

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])&


giriş

["115715", "116616"]

çıktı

23

"u veya v dizeleri arasındaki düzenleme veya Levenshtein mesafesini veren" yerleşik EditDistance'ı kullanır.

Test örneği matematiğine gelince

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

23 döndürür

Sanırım biraz daha golf yapabilirim
Birkaç dakika sürer

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.