स्वाइप टाइप कन्वर्टर


27

लैपटॉप पर टाइप करने की अगली क्रांति स्विफ्टके द्वारा अप्रैल, 2014 को जारी की गई थी । हालाँकि, मैं स्वाइपिंग नैनो क्लोन लिखने वाला पहला व्यक्ति बनना चाहता हूं, लेकिन, जैसा कि मैं वास्तविक-टेक्स्ट लाइब्रेरी में एक अच्छा स्वाइप-टेक्स्ट नहीं पा सकता हूं, और मैं उनके लिए इंतजार नहीं कर सकता, मैं यहां पूछ रहा हूं।

कार्य

एक प्रोग्राम लिखें जो स्वाइप-टेक्स्ट में हो और वास्तविक-टेक्स्ट के समकक्ष आउटपुट हो। उदाहरण:

Input: hgrerhjklo
Output: hello

जब उपयोगकर्ता करता है:

यहाँ छवि विवरण दर्ज करें

अन्य उदाहरण:

Input: wertyuioiuytrtjklkjhgfd
Output: world

Input: poiuytrtyuioiugrewsasdfgbhnmkijnbg
Output: programming

Input: poiuygfdzxcvhjklkjhgres
Output: puzzles

Input: cvhjioiugfde
Output: code

Input: ghiolkjhgf
Output: golf

नियम

  • इस कार्यक्रम में स्टड या आर्गव पर एक स्वाइप 'शब्द' लिया जाएगा
  • स्वाइप इनपुट का पहला और आखिरी अक्षर वास्तविक शब्द के पहले और आखिरी अक्षर के बराबर होगा
  • आप मान सकते हैं कि उपयोगकर्ता यथोचित सीधी रेखाएँ बनाएगा, लेकिन आप इसे सत्यापित करने के लिए नमूना डेटा का उपयोग कर सकते हैं (मैंने नमूना डेटा बनाया है, और मैं अंतिम परीक्षण डेटा बनाऊंगा)
  • अस्पष्ट इनपुट के लिए, आप या तो आउटपुट का चयन कर सकते हैं, लेकिन मैं परीक्षण डेटा से सभी अस्पष्टता को मिटाने की कोशिश करूंगा
  • यह शब्द इस शब्द सूची (लेकिन स्वाइप) में होगा। शब्द सूची वर्तमान निर्देशिका में होगी, और इसे पढ़ा जा सकता है (नई पंक्ति अलग, नाम दिया जाएगा wordlist, कोई विस्तार नहीं)।
  • स्वाइप में केवल लोअरकेस एल्फाबेटिक अक्षर होंगे
  • यदि उपयोगकर्ता कुंजी पर रुकता है तो स्वाइप में डुप्लिकेट वर्ण हो सकते हैं
  • कार्यक्रम को स्टडआउट पर आउटपुट होना चाहिए (मामला कोई फर्क नहीं पड़ता)
  • प्रोग्राम को 0रिटर्न कोड के रूप में लौटना चाहिए
  • आपको रन कमांड, कंपाइल कमांड (यदि आवश्यक हो), नाम और किस इनपुट पथ का उपयोग करना होगा
  • मानक कमियां लागू होती हैं (वे मदद नहीं कर सकती हैं, हालांकि)
  • किसी भी गैर-निर्मित पुस्तकालय की अनुमति नहीं है
  • नियतात्मक, गैर गोल्फ / obfuscated समाधान पसंदीदा
  • कोई फ़ाइल लेखन, नेटवर्किंग, आदि।
  • आपका कोड एक सेकंड या उससे कम में चलना चाहिए (आपका कोड प्रति शब्द एक बार चलाया जाता है)
  • स्कोरिंग रन एक इंटेल i7 हसवेल प्रोसेसर पर चलते हैं, जिसमें 4 वर्चुअल कोड (2 असली वाले) होते हैं, इसलिए यदि आपके पास है तो आप थ्रेड का उपयोग कर सकते हैं
  • 5000 बाइट्स की अधिकतम कोड लंबाई
  • आपके द्वारा उपयोग की जाने वाली भाषा में लिनक्स के लिए एक नि: शुल्क (गैर परीक्षण) संस्करण उपलब्ध होना चाहिए (आर्क लिनक्स, यदि वह मायने रखता है)

जीत का मानदंड

  • विजेता सबसे सटीक समाधान है ( नियंत्रण कार्यक्रम द्वारा दिया गया , प्रदान की गई परीक्षण सूची का उपयोग करके)
  • लोकप्रियता टाई ब्रेकर है
  • स्कोरिंग टेबल को हर कुछ दिनों में अपडेट किया जाएगा
  • समय-आउट और क्रैश की गणना विफल हो जाती है
  • लोकप्रियता के आधार पर यह चुनौती दो सप्ताह या उससे अधिक समय तक चलेगी
  • अंतिम स्कोरिंग शब्दों की एक अलग, यादृच्छिक रूप से चयनित सूची (एक ही शब्द सूची से एक ही लंबाई) का उपयोग करेगा

अन्य

वर्तमान स्कोर बोर्ड

परीक्षण सूची ( लॉग ):

Three Pass Optimizer:Errors: 0/250       Fails: 7/250        Passes: 243/250     Timeouts: 0/250     
Corner Sim:         Errors: 0/250       Fails: 9/250        Passes: 241/250     Timeouts: 0/250     
Discrete Fréchet Distance:Errors: 0/250       Fails: 17/250       Passes: 233/250     Timeouts: 0/250     
Turnaround:         Errors: 0/250       Fails: 18/250       Passes: 232/250     Timeouts: 0/250     
Direction Checker:  Errors: 0/250       Fails: 19/250       Passes: 231/250     Timeouts: 0/250     
Regex Solver:       Errors: 0/250       Fails: 63/250       Passes: 187/250     Timeouts: 0/250

testlist2 ( लॉग ):

Corner Sim:         Errors: 0/250       Fails: 10/250       Passes: 240/250     Timeouts: 0/250     
Three Pass Optimizer:Errors: 2/250       Fails: 14/250       Passes: 234/250     Timeouts: 0/250     
Turnaround:         Errors: 0/250       Fails: 16/250       Passes: 234/250     Timeouts: 0/250     
Direction Checker:  Errors: 0/250       Fails: 17/250       Passes: 233/250     Timeouts: 0/250     
Discrete Fréchet Distance:Errors: 0/250       Fails: 18/250       Passes: 232/250     Timeouts: 0/250     
Regex Solver:       Errors: 0/250       Fails: 67/250       Passes: 183/250     Timeouts: 0/250

फाइनल रन

परीक्षण सूची ( लॉग ):

Corner Sim:         Errors: 0/250       Fails: 14/250       Passes: 236/250     Timeouts: 0/250     
Three Pass Optimizer:Errors: 0/250       Fails: 18/250       Passes: 232/250     Timeouts: 0/250     
Direction Checker:  Errors: 0/250       Fails: 20/250       Passes: 230/250     Timeouts: 0/250     
Turnaround:         Errors: 0/250       Fails: 23/250       Passes: 227/250     Timeouts: 0/250     
Discrete Fréchet Distance:Errors: 0/250       Fails: 30/250       Passes: 220/250     Timeouts: 0/250     
Regex Solver:       Errors: 0/250       Fails: 55/250       Passes: 195/250     Timeouts: 0/250

हर किसी के लिए अच्छा है और hgfdsasdertyuiopoiuy swertyuiopoijnhg!


"A Solution" क्या है? इसका कोड कहां है?
दरवाज़े



@Optimizer सुनिश्चित नहीं हैं कि अन्य मामलों में, लेकिन के बारे में " पी oiuytres एक से आर तों एक रों fghui iugfd एक्स CGU मैं स्नातकीय XS एक sdfghjk एल कू y " क्रम में की "विडंबना", हर पत्र, के अलावा शामिल हैं l, जो दोगुना न हो।
es1024

1
@ ऑप्टिमाइज़र खैर, मुझे लगा कि आपका सबमिशन इसे हरा देगा, लेकिन यह बस नीचे था (थोड़ा ट्वीकिंग ने इसे बदल दिया होगा, मुझे यकीन है)। ऐसा लगता है कि मैं इसे स्वीकार कर सकता हूं, इसलिए ... क्या मुझे (मुझे इसे स्वीकार करने से पुन: प्राप्त करने के लिए प्रकट नहीं होता है)? मैं किसी और को स्वीकार करना चाहता हूं, लेकिन वह नियमों का पालन नहीं कर रहा है (जब तक कि आपको एक अच्छा विचार नहीं मिला है)।
मैटजॉयस

जवाबों:


12

जावास्क्रिप्ट, ईएस 6, तीन पास ऑप्टिमाइज़र, 112 187 235 240 241 243 और 231 234 पास

एक तीन पास फिल्टर जो पहले कीस्ट्रोके अनुक्रम में महत्वपूर्ण कुंजियों का पता लगाता है और फिर तीन फिल्टर के माध्यम से अनुक्रम गुजरता है:

  1. महत्वपूर्ण कुंजियों और मदद करने वाली चाबियों से एक नियमित रूप से गठित RegEx। यह कुंजी के बहुमत के लिए सही परिणाम देता है (लगभग 150)
  2. एक सख्त RegEx सिर्फ महत्वपूर्ण कुंजियों से बना है। यह अतिरिक्त 85 दृश्यों के लिए सही परिणाम देता है
  3. एक तीसरा फ़िल्टर करीबी उत्तरों के बीच अस्पष्टता का पता लगाने के लिए। यह 40% अस्पष्ट मामलों के लिए काम करता है।

कोड

keyboard = {
  x: {},
  y: ['  q      w      e      r      t      y      u      i      o      p',
      '    a      s      d      f      g      h      j      k      l',
      '        z      x      c      v      b      n      m'],
};
for (var i in keyboard.y)
  for (var y of keyboard.y[i])
    keyboard.x[y] = +i*7;
p = C => (x=keyboard.x[C],{x, y: keyboard.y[x/7].indexOf(C)})
angle = (L, C, R) => (
  p0 = p(L), p1 = p(C), p2 = p(R),
  a = Math.pow(p1.x-p0.x,2) + Math.pow(p1.y-p0.y,2),
  b = Math.pow(p1.x-p2.x,2) + Math.pow(p1.y-p2.y,2),
  c = Math.pow(p2.x-p0.x,2) + Math.pow(p2.y-p0.y,2),
  Math.acos((a+b-c) / Math.sqrt(4*a*b))/Math.PI*180
)
corner = (L, C, R, N, W) => {
  if (skip) {
    skip = false;
    return [];
  } 
  ngl = angle(L, C, R);
  if (ngl < 80) return [C + "{1,3}"]
  if (ngl < 115 && p(L).x != p(R).x && p(L).x != p(C) && p(R).x != p(C).x && Math.abs(p(L).y - p(R).y) < 5) return [C + "{0,3}"]
  if (ngl < 138) {
    if (N && Math.abs(ngl - angle(C, R, N)) < 6) {
      skip = true;
      return [L + "{0,3}", "([" + C + "]{0,3}|[" + R + "]{0,3})?", N + "{0,3}"]
    }
    return [C + "{0,3}"]
  }
  return ["([" + L + "]{0,3}|[" + C + "]{0,3}|[" + R + "]{0,3})?"]
}
f = S => {
  for (W = [S[0] + "{1,2}"],i = 1; i < S.length - 1; i++)
    W.push(...corner(S[i - 1], S[i], S[i + 1], S[i + 2], W))
  return [
    new RegExp("^" + W.join("") + S[S.length - 1] + "{1,3}$"),
    new RegExp("^" + W.filter(C=>!~C.indexOf("[")).join("") + S[S.length - 1] + "{1,3}$")
  ]
}
thirdPass = (F, C) => {
  if (!F[0]) return null
  F = F.filter((s,i)=>!F[i - 1] || F[i - 1] != s)
  FF = F.map(T=>[...T].filter((c,i)=>!T[i - 1] || T[i - 1] != c).join(""))
  if (FF.length == 1) return F[0];
  if (FF.length < 6 && FF[0][2] && FF[1][2] && FF[0][0] == FF[1][0] && FF[0][1] == FF[1][1])
    if (Math.abs(F[0].length - F[1].length) < 1)
      for (i=0;i<Math.min(F[0].length, FF[1].length);i++) {
        if (C.indexOf(FF[0][i]) < C.indexOf(FF[1][i])) return F[0]
        else if (C.indexOf(FF[0][i]) > C.indexOf(FF[1][i])) return F[1]
      }
  return F[0]
}
var skip = false;
SwiftKey = C => (
  C = [...C].filter((c,i)=>!C[i - 1] || C[i - 1] != c).join(""),
  skip = false, matched = [], secondPass = [], L = C.length, reg = f(C),
  words.forEach(W=>W.match(reg[0])&&matched.push(W)),
  words.forEach(W=>W.match(reg[1])&&secondPass.push(W)),
  matched = matched.sort((a,b)=>Math.abs(L-a.length)>Math.abs(L-b.length)),
  secondPass = secondPass.sort((a,b)=>Math.abs(L-a.length)>Math.abs(L-b.length)),
  first = matched[0], second = secondPass[0], third = thirdPass(secondPass.length? secondPass: matched, C),
  second && second.length >= first.length - 1? first != third ? third: second: third.length >= first.length ? third: first
)

// For use by js shell of latest firefox
print(SwiftKey(readline()));

कोड एक चर कहलाता wordsहै जिसे वर्तमान कहा जाता है जो इस पृष्ठ के सभी शब्दों की एक सरणी है

कोड इन एक्शन यहाँ देखें

यहां कार्रवाई में परीक्षण के मामलों को देखें

उपरोक्त दोनों लिंक केवल एक नवीनतम फ़ायरफ़ॉक्स (33 और ऊपर) (ईएस 6 के कारण) पर काम करते हैं।


हाँ! मैं गोले बरसा रहा हूं। आप keypos.csvअब उचित फ़ाइल का भी उपयोग कर सकते हैं। IO फ़ंक्शंस उपलब्ध हैं जिन्हें डेवलपर.
mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/…

यह ठीक है, लेकिन मेरे कीबोर्ड के कोणों के साथ स्वाइप किए गए हैं, इसलिए यह आपकी पसंद है (हालांकि, आपके स्कोर को प्रभावित नहीं करता है!)
matsjoyce


240 पास बकाया है! मैंने सोचा होगा कि अस्पष्टताएं ऐसे अच्छे परिणामों को रोकेंगी। मैं उत्सुक हूँ कि यह अंतिम परीक्षण सेट पर कैसा प्रदर्शन करेगा।
एमिल

@ ईमिल - हाँ, मुझे भी यही देखने का इंतज़ार है।
ऑप्टिमाइज़र

9

रूबी, रेगेक्स सॉल्वर - 30 140 176 180 182 187 और 179 183 पास

मैं बाद में स्कोर का पता लगाऊंगा। यहाँ बहुत भोला समाधान है जो कीबोर्ड लेआउट को ध्यान में नहीं रखता है:

words = File.readlines('wordlist').map(&:chomp)

swipe = ARGV.shift
puts words.select {|word| word[0] == swipe[0] &&
                          word[-1] == swipe[-1]}
          .select {|word|
              chars = [word[0]]
              (1..word.size-1).each {|i| chars << word[i] if word[i] != word[i-1]}
              swipe[Regexp.new('^'+chars.join('.*')+'$')]
          }.sort_by {|word| word.size}[-1]

यह ARGV से इनपुट लेता है और परिणाम प्रिंट करता है। मैं सिर्फ पहले और आखिरी अक्षर से शब्द सूची को फ़िल्टर कर रहा हूं, और मैं इनपुट के खिलाफ शेष सभी शब्दों की कोशिश कर रहा हूं (डुप्लिकेट पत्रों को समाप्त कर रहा हूं और ^g.*u.*e.*s$"अनुमान" के लिए एक regex का उपयोग कर रहा हूं ) और यदि उनमें से पहले को वापस कर देता हूं कई समाधान हैं।

इसे वैसे ही चलाएं

ruby regex-solver.rb cvhjioiugfde

कोई और, इस कदम को पहले फ़िल्टर के रूप में पुन: उपयोग करने के लिए स्वतंत्र महसूस करता है - मेरा मानना ​​है कि यह किसी भी सही शब्द को बाहर नहीं फेंकेगा, इसलिए यह प्रारंभिक जांच बेहतर एल्गोरिदम के लिए खोज स्थान को काफी कम कर सकती है।

संपादित करें: ओपी के सुझाव के बाद, मैं अब उम्मीदवारों में से सबसे लंबे समय तक चयन कर रहा हूं, जो एक अच्छा अनुमान है।

डुप्लिकेट पत्रों के बारे में मुझे याद दिलाने के लिए es1024 के लिए भी धन्यवाद।


किया हुआ। आपके लॉग इन github.com/matsjoyce/codegolf-swipe-type/blob/master/logs/… मुझे लगता है कि समस्या यह है कि यह संभावित समाधानों को बेतरतीब ढंग से चुनता है, जिसे सबसे लंबे समय तक या कुछ और का चयन करके सुधार किया जा सकता है।
मत्सजॉयस

मुझे लगता है कि यह एक दूसरे के बगल में दो समान अक्षरों के साथ सभी सही शब्दों को बाहर फेंक सकता है, जैसे कि paradoxically, lकेवल इनपुट में एक बार दिखाई देगा, बल्कि रेगेक्स द्वारा दो बार की मांग के रूप में।
es1024 1

@ es1024, आह, धन्यवाद, जब मैंने पहली बार इस एल्गोरिदम को सैंडबॉक्स में वापस करने का प्रस्ताव दिया, तो मैं वास्तव में इसके बारे में जानता था, लेकिन कल के बारे में भूल गया। बाद में ठीक कर देंगे।
मार्टिन एंडर

7

सी ++, असतत दूरी दूरी - 201 220 222 232 और 232 पास

मेरे लिए, यह समस्या बहुत हद तक फ्रैचेट डिस्टेंस के लिए कहलाती है जो दुर्भाग्य से गणना के लिए बहुत कठिन है।

बस मज़े के लिए, मैंने कम्प्यूटिंग डिसक्रीट फ़्रेटेट डिस्टेंस (1994) में थॉमस एटर और हेइक्की मनिला द्वारा वर्णित एक असतत सन्निकटन को लागू करके समस्या से संपर्क करने की कोशिश की है ।

सबसे पहले, मैं सूची में सभी शब्दों को फ़िल्टर करने के लिए दूसरों के रूप में एक ही दृष्टिकोण का उपयोग कर रहा हूं जो इनपुट के बाद के हैं (एक ही चरित्र के कई अनुक्रमिक घटनाओं के लिए भी लेखांकन)। फिर, मैं प्रत्येक शब्द के अक्षर से अक्षर तक बहुभुज वक्र को मध्यवर्ती बिंदुओं से भर रहा हूं और इसे इनपुट वक्र के खिलाफ मैच करता हूं। अंत में, मैं हर दूरी को शब्द की लंबाई से विभाजित करता हूं और न्यूनतम स्कोर लेता हूं।

अब तक, विधि उतनी अच्छी तरह से काम नहीं करती है जितनी मैंने आशा की थी (यह कोड उदाहरण को "chide" के रूप में पहचानता है), लेकिन यह सिर्फ उन बगों का परिणाम हो सकता है जो मुझे अभी तक नहीं मिले हैं। इसके अलावा, एक अन्य विचार यह होगा कि फ़्रेचेट दूरी ("औसत" "अधिकतम कुत्ते पट्टा लंबाई" के बजाय) की अन्य विविधताओं का उपयोग किया जाए।

संपादित करें: अब, मैं "औसत कुत्ते पट्टा लंबाई" के लिए एक सन्निकटन का उपयोग कर रहा हूं। इसका मतलब यह है कि मुझे दोनों रास्तों के बीच एक ऑर्डर की गई मैपिंग मिल रही है जो सभी दूरी के योग को कम करती है और बाद में इसे दूरी की संख्या से विभाजित करती है।

यदि शब्दकोश शब्द में एक ही चरित्र दो या अधिक बार दिखाई देता है, तो मैं केवल एक नोड को पथ में रखता हूं।

#include<iostream>
#include<fstream>
#include<vector>
#include<map>
#include<algorithm>
#include<utility>
#include<cmath>

using namespace std;

const double RESOLUTION = 3.2;

double dist(const pair<double, double>& a, const pair<double, double>& b) {
    return sqrt((a.first - b.first) * (a.first - b.first) + (a.second - b.second) * (a.second - b.second));
}

double helper(const vector<pair<double, double> >& a,
        const vector<pair<double, double> >& b,
        vector<vector<double> >& dp,
        int i,
        int j) {
    if (dp[i][j] > -1)
        return dp[i][j];
    else if (i == 0 && j == 0)
        dp[i][j] = dist(a[0], b[0]);
    else if (i > 0 && j == 0)
        dp[i][j] = helper(a, b, dp, i - 1, 0) +
                   dist(a[i], b[0]);
    else if (i == 0 && j > 0)
        dp[i][j] = helper(a, b, dp, 0, j - 1) +
                   dist(a[0], b[j]);
    else if (i > 0 && j > 0)
        dp[i][j] = min(min(helper(a, b, dp, i - 1, j),
                           helper(a, b, dp, i - 1, j - 1)),
                       helper(a, b, dp, i, j - 1)) +
                   dist(a[i], b[j]);
    return dp[i][j];
}

double discretefrechet(const vector<pair<double, double> >& a, const vector<pair<double, double> >& b) {
    vector<vector<double> > dp = vector<vector<double> >(a.size(), vector<double>(b.size(), -1.));
    return helper(a, b, dp, a.size() - 1, b.size() - 1);
}

bool issubsequence(string& a, string& b) {
    // Accounts for repetitions of the same character: hallo subsequence of halo
    int i = 0, j = 0;
    while (i != a.size() && j != b.size()) {
        while (a[i] == b[j])
            ++i;
        ++j;
    }
    return (i == a.size());
}

int main() {
    string swipedword;
    cin >> swipedword;

    ifstream fin;
    fin.open("wordlist");
    map<string, double> candidatedistance = map<string, double>();
    string readword;
    while (fin >> readword) {
        if (issubsequence(readword, swipedword) && readword[0] == swipedword[0] && readword[readword.size() - 1] == swipedword[swipedword.size() - 1]) {
            candidatedistance[readword] = -1.;
        }
    }
    fin.close();

    ifstream fin2;
    fin2.open("keypos.csv");
    map<char, pair<double, double> > keypositions = map<char, pair<double, double> >();
    char rc, comma;
    double rx, ry;
    while (fin2 >> rc >> comma >> rx >> comma >> ry) {
        keypositions[rc] = pair<double, double>(rx, ry);
    }
    fin2.close();

    vector<pair<double, double> > swipedpath = vector<pair<double, double> >();
    for (int i = 0; i != swipedword.size(); ++i) {
        swipedpath.push_back(keypositions[swipedword[i]]);
    }

    for (map<string, double>::iterator thispair = candidatedistance.begin(); thispair != candidatedistance.end(); ++thispair) {
        string thisword = thispair->first;
        vector<pair<double, double> > thispath = vector<pair<double, double> >();
        for (int i = 0; i != thisword.size() - 1; ++i) {
            pair<double, double> linestart = keypositions[thisword[i]];
            pair<double, double> lineend = keypositions[thisword[i + 1]];
            double linelength = dist(linestart, lineend);
            if (thispath.empty() || linestart.first != thispath[thispath.size() - 1].first || linestart.second != thispath[thispath.size() - 1].second)
                thispath.push_back(linestart);
            int segmentnumber = linelength / RESOLUTION;
            for (int j = 1; j < segmentnumber; ++j) {
                thispath.push_back(pair<double, double>(linestart.first + (lineend.first - linestart.first) * ((double)j) / ((double)segmentnumber),
                                    linestart.second + (lineend.second - lineend.second) * ((double)j) / ((double)segmentnumber)));
            }
        }
        pair<double, double> lastpoint = keypositions[thisword[thisword.size() - 1]];
        if (thispath.empty() || lastpoint.first != thispath[thispath.size() - 1].first || lastpoint.second != thispath[thispath.size() - 1].second)
        thispath.push_back(lastpoint);

        thispair->second = discretefrechet(thispath, swipedpath) / (double)(thispath.size());
    }

    double bestscore = 1e9;
    string bestword = "";
    for (map<string, double>::iterator thispair = candidatedistance.begin(); thispair != candidatedistance.end(); ++thispair) {
        double score = thispair->second;
        if (score < bestscore) {
            bestscore = score;
            bestword = thispair->first;
        }
        // cout << thispair->first << ": " << score << endl;
    }
    cout << bestword << endl;

    return 0;
}

मैंने कोड को क्लैंग के साथ संकलित किया है, लेकिन g++ ./thiscode.cpp -o ./thiscodeयह भी ठीक काम करना चाहिए।


1
हाँ! किसी ने अंत में एक बड़े वसा एल्गोरिदम नाम के साथ एक समाधान जोड़ा है! आपका लॉग github.com/matsjoyce/codegolf-swipe-type/blob/master/logs/… पर है
matsjoyce

1
चलो बल्कि इसे एक बड़ी मोटी कंप्यूटर विज्ञान समस्या के लिए एक सरल गतिशील प्रोग्रामिंग एल्गोरिदम कहते हैं।
कैमेलनेक

किसी कारण से, यह इनपुट के लिए विफल होता दिख रहा है programmijng- यह मुझे देता है pang
23:15 बजे

वह अजीब है। मुझे programmingजैसा चाहिए वैसा मिल रहा है । क्या आप लाइन को अनकम्प्लीट कर सकते हैं // cout << thispair->first << ": " << score << endl;और परिणामी स्कोर पेस्ट कर सकते हैं?
CamelNeck

6

पायथन 2, टर्नरॉइड्स, 224 226 230 232 और 230 234 पास

यह काफी सीधे आगे का दृष्टिकोण है:

  • उन बिंदुओं को खोजें जहां अक्षरों का प्रवाह दिशा बदलता है (प्लस शुरू और अंत)।
  • सबसे लंबे शब्द को आउटपुट करें जिसमें ये सभी मोड़ शामिल हैं।
import sys, csv, re

wordlistfile = open('wordlist', 'r')
wordlist = wordlistfile.read().split('\n')

layout = 'qwertyuiop asdfghjkl  zxcvbnm'
keypos = dict((l, (2*(i%11)+i/11, i/11)) for i,l in enumerate(layout))

#read input from command line argument
input = sys.argv[1]

#remove repeated letters
input = ''.join(x for i,x in enumerate(input) if i==0 or x!=input[i-1])

#find positions of letters on keyboard
xpos = map(lambda l: keypos[l][0], input)
ypos = map(lambda l: keypos[l][1], input)

#check where the direction changes (neglect slight changes in x, e.g. 'edx')
xpivot = [(t-p)*(n-t)<-1.1 for p,t,n in zip(xpos[:-2], xpos[1:-1], xpos[2:])]
ypivot = [(t-p)*(n-t)<0 for p,t,n in zip(ypos[:-2], ypos[1:-1], ypos[2:])]
pivot = [xp or yp for xp,yp in zip(xpivot, ypivot)]

#the first and last letters are always pivots
pivot = [True] + pivot + [True]

#build regex
regex = ''.join(x + ('+' if p else '*') for x,p in zip(input, pivot))
regexobj = re.compile(regex + '$')

#find all words that match the regex and output the longest one
words = [w for w in wordlist if regexobj.match(w)]
output = max(words, key=len) if words else input
print output

ऐसे दोड़ो

python turnarounds.py tyuytrghn

समाधान बहुत मजबूत नहीं है। एक भी गलत कीस्ट्रोक इसे विफल कर देगा। हालाँकि, चूंकि परीक्षण मामलों के सेट में बहुत कम गलतियाँ नहीं हैं, इसलिए यह काफी अच्छा प्रदर्शन करता है, केवल कुछ मामलों में भ्रमित हो रहा है जहाँ यह बहुत लंबे शब्दों को चुनता है।

संपादित करें: मैंने प्रदान की गई महत्वपूर्ण स्थिति फ़ाइल का उपयोग नहीं करने के लिए इसे थोड़ा बदल दिया लेकिन एक सरलीकृत लेआउट। यह मेरे एल्गोरिथ्म के लिए आसान बनाता है क्योंकि फ़ाइल में कुंजियाँ समान रूप से नहीं होती हैं। मैं अस्पष्ट मामलों के लिए कुछ तदर्थ टाईब्रेकर्स को शामिल करके थोड़ा बेहतर परिणाम प्राप्त कर सकता हूं, लेकिन यह इस विशेष परीक्षण सेट के लिए अति-अनुकूलन होगा। कुछ विफल रहते हैं जो वास्तव में अस्पष्ट नहीं हैं, लेकिन मैं अपने सरल एल्गोरिथ्म के साथ नहीं पकड़ता क्योंकि यह केवल 90 डिग्री से अधिक के दिशा परिवर्तन पर विचार करता है।


बहुत बढ़िया! वर्तमान नेता! यदि आप लॉग देखना चाहते हैं, तो गोटो github.com/matsjoyce/codegolf-swipe-type/blob/master/logs/…
matsjoyce

@ मैट्सजॉय: मैंने इस प्रश्न के लिए एक टिप्पणी जोड़ी है जिसमें दो वर्तनी की गलतियाँ हैं जो मुझे लगता है कि मुझे मिली हैं। :)
एमिल

हां, धन्यवाद, मैं इसे एक और चेक दे रहा हूं। मुझे इस बात का पूरा यकीन नहीं है कि अस्पष्ट मामलों का क्या करना है, हालाँकि।
21

@ मैट्सजॉय: कीबोर्ड पर संभावित रास्तों में से किसी एक को चुनकर कुछ अस्पष्टताओं को हल किया जा सकता है। ईजी bratsहो सकता है 'bgrdsasdrtrds'जिसके साथ भ्रमित नहीं किया जा सकता है breasts। हालाँकि, मुझे भी कोई आपत्ति नहीं होगी अगर आपने इसे छोड़ दिया है।
एमिल

सच है, यह काम करेगा। मुझे बस इस बात की चिंता है कि अगर इस सेट को भी 'इष्टतम' बना दिया जाए, और अंतिम स्कोरिंग सेट को अधिक जांच के लिए नहीं रखा जाए, तो कुछ समाधान भी प्रदर्शन नहीं कर सकते हैं
मैट

6

पीएचपी, दिशा परीक्षक, 203 213 216 229 231 और 229 233 पास

यह उन शब्दों की एक सूची प्राप्त करने के लिए शब्दकोश के माध्यम से एक सरल पास से शुरू होता है, जिनके अक्षर इनपुट में सभी मौजूद हैं (मार्टिन ने यहां क्या किया ), और l.*इसके बजाय केवल डुप्लिकेट l.*l.*होने की बजाय केवल जांच कर रहा lहै।

यहां सबसे लंबा शब्द एक चर में सहेजा गया है।

एक और जाँच तब की जाती है, जो उन बिंदुओं पर कुंजियों के आधार पर की जाती है, जहाँ स्वाइप दिशा बदलता रहता है (+ / 0 से - या - / - 0 से +, या तो x या y में)। पात्रों की इस सूची के खिलाफ संभावित शब्दों की सूची की जाँच की जाती है, और जो शब्द मेल नहीं खाते हैं, उन्हें समाप्त कर दिया जाता है। यह दृष्टिकोण सटीक होने के लिए स्वाइपिंग में तेज मोड़ पर निर्भर करता है।

शेष सबसे लंबा शब्द आउटपुट है, या यदि कोई शब्द नहीं बचा है, तो पहले से सबसे लंबा शब्द इसके बजाय आउटपुट है।

संपादित करें: एक क्षैतिज रेखा में सभी वर्णों को जोड़ा जाता है, जिससे जांच के लिए संभव मानों के रूप में दिशा में परिवर्तन होता है।

PHP 5.4 की आवश्यकता है (या सभी के [..]साथ बदलें array(..))।

<?php
function get_dir($a, $b){
    $c = [0, 0];
    if($a[0] - $b[0] < -1.4) $c[0] = 1;
    else if($a[0] - $b[0] > 1.4) $c[0] = -1;
    if($a[1] < $b[1]) $c[1] = 1;
    else if($a[1] > $b[1]) $c[1] = -1;
    return $c;
}
function load_dict(){
    return explode(PHP_EOL, file_get_contents('wordlist'));
}

$coord = [];
$f = fopen('keypos.csv', 'r');
while(fscanf($f, "%c, %f, %f", $c, $x, $y)){
    $coord[$c] = [$x, $y];  
}
fclose($f);

$dict = load_dict();
$in = $argv[1];
$possib = [];

foreach($dict as $c){
    if($c[0] == $in[0]){
        $q = strlen($c);
        $r = strlen($in);
        $last = '';
        $fail = false;
        $i = $j = 0;
        for($i = 0; $i < $q; ++$i){
            if($last == $c[$i]) continue;
            if($j >= $r){
                $fail = true;
                break;
            }
            while($c[$i] != $in[$j++])
                if($j >= $r){
                    $fail = true; 
                    break;
                }
            if($fail) break;
            $last = $c[$i];
        }
        if(!$fail) 
            $possib[] = $c;
    }
}

$longest = '';
foreach($possib as $p){
    if(strlen($p) > strlen($longest))
        $longest = $p;
}

$dir = [[0, 0]];
$cdir = [0, 0];
$check = '/^' . $in[0] . '.*?';
$olst = []; $p = 1;

$len = strlen($in);
for($i = 1; $i < $len; ++$i){
    $dir[$i] = get_dir($coord[$in[$i - 1]], $coord[$in[$i]]);
    $olddir = $cdir;
    $newdir = $dir[$i];
    $xc = $olddir[0] && $newdir[0] && $newdir[0] != $olddir[0];
    $yc = $olddir[1] && $newdir[1] && $newdir[1] != $olddir[1];
    if($xc || $yc){ // separate dir from current dir
        if($yc && !$xc && $dir[$i - 1][1] == 0){
            $tmp = '';
            for($j = $i - 1; $j >= 0 && $dir[$j][1] == 0; --$j){
                $tmp = '(' . $in[$j-1] . '.*?)?' . $tmp;
            }
            $olst[] = range($p, $p + (($i - 1) - $j));
            $p += ($i - 1) - $j + 1;
            $check .= $tmp . '(' . $in[$i - 1] . '.*?)?';
        }else{
            $check .= $in[$i - 1] . '.*?';
        }
        $cdir = $dir[$i];
    }else{
        if(!$cdir[0]) $cdir[0] = $dir[$i][0]; 
        if(!$cdir[1]) $cdir[1] = $dir[$i][1]; 
    }
}
$check .= substr($in, -1) . '$/';
$olstc = count($olst);
$res = [];
foreach($possib as $p){
    if(preg_match($check, $p, $match)){
        if($olstc){
            $chk = array_fill(0, $olstc, 0);
            for($i = 0; $i < $olstc; ++$i){
                foreach($olst[$i] as $j){
                    if(isset($match[$j]) && $match[$j]){
                        ++$chk[$i];
                    }
                }
                // give extra weight to the last element of a horizontal run
                if(@$match[$olst[$i][count($olst[$i])-1]])
                    $chk[$i] += 0.5;
            }
            if(!in_array(0, $chk)){
                $res[$p] = array_sum($chk);
            }
        }else{
            $res[$p] = 1;
        }
    }
}
$possib = array_keys($res, @max($res));
$newlong = '';
foreach($possib as $p){
    if(strlen($p) > strlen($newlong))
        $newlong = $p;
}
if(strlen($newlong) == 0) echo $longest;
else echo $newlong;

@matsjoyce ने सवाल के माध्यम से पढ़ते हुए उस बुलेट बिंदु को याद किया। कोड अब से पदों का उपयोग करता हैkeypos.csv
es1024

@ es1024 250 परीक्षण मामलों का हिस्सा नहीं होने के बावजूद, शब्द सूची में तीन लगातार अक्षरों के साथ 238 शब्द हैं (अब तक, मैंने सभी चेक किए गए शब्द समाप्त हो रहे हैं sss) - मुझे नहीं लगता कि आपका डुप्लिकेट उन्मूलन उन लोगों को पकड़ लेगा।
मार्टिन एंडर

यदि आपको इसकी आवश्यकता है, तो आपके लॉग github.com/matsjoyce/codegolf-swipe-type/blob/master/logs/…
matsjoyce

3

पायथन 3, कॉर्नर सिम्युलेटर, 241 और 240 पास

कलन विधि:

  • डेडुप्लिकेट (समान वर्ण के लगातार रन निकालें) इनपुट और शब्द सूची में सभी शब्द (मूल शब्दों को वापस लाने के लिए एक शब्दकोश का उपयोग करके)
  • उन सभी शब्दों को निकालें, जो स्वाइप की शुरुआत और समाप्ति के साथ शुरू और समाप्त नहीं होते हैं (पहले पास)
  • 80 डिग्री से अधिक सभी कोनों से एक रेगेक्स बनाएं, फिर उन सभी शब्दों को हटा दें जो इस (दूसरे पास) से मेल नहीं खाते
  • प्रत्येक शब्द को Regex (जैसे Regex Solver) के माध्यम से स्वाइप करें, फिर स्वाइप को सैद्धांतिक रूप से सीधी रेखाओं की एक श्रृंखला में विभाजित करें, और जांचें कि क्या वे सीधे हैं और उस लाइन ( significant_letterफ़ंक्शन) के साथ चलती उंगली से उत्पन्न हो सकते हैं (तीसरा पास)
  • सीधी रेखाओं के निकटता द्वारा शब्दों को क्रमबद्ध करें
  • फिर टाई ब्रेकर के रूप में लंबाई का उपयोग करें (अब बेहतर है)
  • फिर अंतिम टाई ब्रेकर के रूप में लेवेन्सहाइट दूरी का उपयोग करें
  • आउटपुट शब्द!

कोड:

# Corner Sim

from math import atan, degrees, pi, factorial, cos, radians
import csv
import re
import sys

keys = {}
key_size = 1.5
for line in open("keypos.csv"):
    k, x, y = map(str.strip, line.split(","))
    keys[k] = float(x), float(y)


def deduplicate(s):
    return s[0] + "".join(s[i + 1] for i in range(len(s) - 1) if s[i + 1] != s[i])


def angle(coord1, coord2):
    x1, y1, x2, y2 = coord1 + coord2
    dx, dy = x2 - x1, y1 - y2
    t = abs(atan(dx/dy)) if dy else pi / 2
    if dx >= 0 and dy >= 0: a = t
    elif dx >= 0 and dy < 0: a = pi - t
    elif dx < 0 and dy >= 0: a = 2 * pi - t
    else: a = t + pi
    return degrees(a)


def significant_letter(swipe):
    if len(swipe) <= 2: return 0
    x1, y1, x2, y2 = keys[swipe[0]] + keys[swipe[-1]]
    m = 0 if x2 == x1 else (y2 - y1) / (x2 - x1)
    y = lambda x: m * (x - x1) + y1
    def sim_fun(x2, y2):
        try: return (x2 / m + y2 - y1 + x1 * m) / (m + 1 / m)
        except ZeroDivisionError: return x2
    dists = []
    for i, key in enumerate(swipe[1:-1]):
        sx, bx = min(x1, x2), max(x1, x2)
        pos_x = max(min(sim_fun(*keys[key]), bx), sx)
        sy, by = min(y1, y2), max(y1, y2)
        pos_y = max(min(y(pos_x), by), sy)
        keyx, keyy = keys[key]
        dist = ((keyx - pos_x) ** 2 + (keyy - pos_y) ** 2) ** 0.5
        a = angle((keyx, keyy), (pos_x, pos_y))
        if 90 <= a <= 180: a = 180 - a
        elif 180 <= a <= 270: a = a - 180
        elif 270 <= a <= 360: a = 360 - a
        if a > 45: a = 90 - a
        h = key_size / 2 / cos(radians(a))
        dists.append((max(dist - h, 0), i + 1, key))
    return sorted(dists, reverse=True)[0][0]


def closeness2(s, t):
    # https://en.wikipedia.org/wiki/Levenshtein_distance
    if s == t: return 0
    if not len(s): return len(t)
    if not len(t): return len(s)
    v0 = list(range(len(t) + 1))
    v1 = list(range(len(t) + 1))
    for i in range(len(s)):
        v1[0] = i + 1
        for j in range(len(t)):
            cost = 0 if s[i] == t[j] else 1
            v1[j + 1] = min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost)
        for j in range(len(v0)):
            v0[j] = v1[j]
    return v1[len(t)] / len(t)


def possible(swipe, w, s=False):
    m = re.match("^" + "(.*)".join("({})".format(i) for i in w) + "$", swipe)
    if not m or s:
        return bool(m)
    return closeness1(swipe, w) < 0.8


def closeness1(swipe, w):
    m = re.match("^" + "(.*)".join("({})".format(i) for i in w) + "$", swipe)
    unsigpatches = []
    groups = m.groups()
    for i in range(1, len(groups), 2):
        unsigpatches.append(groups[i - 1] + groups[i] + groups[i + 1])
    if debug: print(unsigpatches)
    sig = max(map(significant_letter, unsigpatches))
    if debug: print(sig)
    return sig


def find_closest(swipes):
    level1, level2, level3, level4 = swipes
    if debug: print("Loading words...")
    words = {deduplicate(i.lower()): i.lower() for i in open("wordlist").read().split("\n") if i[0] == level1[0] and i[-1] == level1[-1]}
    if debug: print("Done first filter (start and end):", words)
    r = re.compile("^" + ".*".join(level4) + "$")
    pos_words2 = list(filter(lambda x: bool(r.match(x)), words))
    if debug: print("Done second filter (sharpest points):", pos_words2)
    pos_words = pos_words2 or words
    pos_words = list(filter(lambda x: possible(level1, x), pos_words)) or list(filter(lambda x: possible(level1, x, s=True), pos_words))
    if debug: print("Done third filter (word regex):", pos_words)
    sorted_pos_words = sorted((closeness1(level1, x), -len(x), closeness2(level1, x), x)
                              for x in pos_words)
    if debug: print("Closeness matching (to", level2 + "):", sorted_pos_words)
    return words[sorted_pos_words[0][3]]


def get_corners(swipe):
    corners = [[swipe[0]] for i in range(4)]
    last_dir = last_char = None
    for i in range(len(swipe) - 1):
        dir = angle(keys[swipe[i]], keys[swipe[i + 1]])
        if last_dir is not None:
            d = abs(last_dir - dir)
            a_diff = min(360 - d, d)
            corners[0].append(last_char)
            if debug: print(swipe[i], dir, last_dir, a_diff, end=" ")
            if a_diff >= 55:
                if debug: print("C", end=" ")
                corners[1].append(last_char)
            if a_diff >= 65:
                if debug: print("M", end=" ")
                corners[2].append(last_char)
            if a_diff >= 80:
                if debug: print("S", end=" ")
                corners[3].append(last_char)
            if debug: print()
        last_dir, last_char = dir, swipe[i + 1]
    tostr = lambda x: deduplicate("".join(x + [swipe[-1]]).lower())
    return list(map(tostr, corners))


if __name__ == "__main__":
    debug = "-d" in sys.argv
    if debug: sys.argv.remove("-d")
    swipe = deduplicate(sys.argv[1] if len(sys.argv) > 1 else input()).lower()
    corners = get_corners(swipe)
    if debug: print(corners)
    print(find_closest(corners))

साथ दौड़ो python3 entries/corner_sim.py


यह एक वैध जवाब था। जवाब देने की जरूरत नहीं है।
ऑप्टिमाइज़र

@ ऑप्टिमाइज़र खैर, मेटा चर्चा आपके उत्तर को स्वीकार करने के पक्ष में लगती है, इसलिए मेरे द्वारा इसका जुर्माना किया गया है।
20

केवल उस मेटा चर्चा को पढ़ने के बाद, मैं आपके निर्णय के साथ ठीक था, लेकिन यह भी अच्छा है (बेहतर) :)
ऑप्टिमाइज़र
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.