इष्टतम यहूदी toenail काटने एल्गोरिथ्म क्या है?


118

मैं एक मशीन के लिए सॉफ्टवेयर पर काम कर रहा हूं जो स्वचालित रूप से toenails ट्रिम कर देगा, ताकि उपयोगकर्ता बस अपने पैरों को इसमें डाल सकें और इसे मैन्युअल रूप से करने के बजाय उन्हें काटने या नाखून कतरनी का उपयोग करने के बजाय चला सकते हैं।

हमारे संभावित उपयोगकर्ता आधार का एक बड़ा प्रतिशत यहूदी होने की संभावना है, और, जाहिर है, क्रमिक क्रम में टोकन ( या नाखूनों ) को ट्रिम न करने के बारे में एक परंपरा है।

इस परंपरा के सटीक अनुप्रयोग पर विवादास्पद राय दी जा रही है, लेकिन हमें लगता है कि निम्नलिखित नियम ऐसे लोगों को शामिल करने के लिए पर्याप्त हैं, जिनकी धार्मिक प्रथाओं में क्रम में टोनेल काटने पर प्रतिबंध है:

  • किसी भी दो निकटवर्ती toenails को लगातार नहीं काटा जाना चाहिए
  • बाएं पैर पर काटने का क्रम दाहिने पैर पर अनुक्रम से मेल नहीं खाना चाहिए
  • लगातार दो रनों पर काटने का क्रम समान नहीं होना चाहिए। दृश्यों को आसानी से अनुमानित नहीं किया जाना चाहिए, इसलिए एक वैकल्पिक अनुक्रम को हार्डकोड करना काम नहीं करता है।

इस तरह हमने पैर की उंगलियों को नंबर देने का फैसला किया है:

5 4 3 2 1  1 2 3 4 5
Left foot  Right foot

मैंने समस्या को हल करने के लिए कोड लिखा है, लेकिन उपयोग किया गया एल्गोरिथ्म उप-इष्टतम है: वास्तव में, सबसे खराब स्थिति प्रदर्शन ओ (∞) है । जिस तरह से यह काम करता है वह बोगोसॉर्ट के बराबर है । यहाँ उपयोग किए गए वास्तविक कोड का छद्म कोड सरल है:

function GenerateRandomSequence
   sequence = Array[5]
   foreach (item in sequence)
       item = RandomNumberBetween(1,5)
   return sequence

function GetToenailCuttingOrder
   while (true)
      sequence = GenerateRandomSequence()
      if (!AllItemsAreUnique(sequence))
         continue
      if (NoTwoAdjacentItemsHaveConsecutiveNumbers(sequence))
         return sequence

do
    leftFootSequence = GetToenailCuttingOrder()
    rightFootSequence = GetToenailCuttingOrder()
until (leftFootSequence != rightFootSequence &&
       leftFootSequence != leftFootSequenceFromLastRun &&
       rightFootSequence != rightFootSequenceFromLastRun)

मूल रूप से, यह यादृच्छिक अनुक्रम उत्पन्न करता है और जांचता है कि क्या वे मानदंडों को पूरा करते हैं। यदि यह मानदंडों को पूरा नहीं करता है, तो यह खत्म हो जाता है। यह हास्यास्पद रूप से लंबे समय तक नहीं लेता है, लेकिन यह बहुत अप्रत्याशित है।

मुझे एहसास है कि जिस तरह से मैं वर्तमान में कर रहा हूं वह बहुत भयानक है, लेकिन मुझे बेहतर तरीके से आने में परेशानी हो रही है। क्या आप में से कोई भी अधिक सुरुचिपूर्ण और प्रदर्शनकारी एल्गोरिथम सुझा सकता है?


28
इससे होमवर्क की समस्या जैसी बदबू आती है। अन्यथा, केवल अनुक्रम को हार्डकोड क्यों नहीं?
माइकल ब्राउन

24
मैंने नाखूनों को काटने के बारे में सुना है, लेकिन toenails?
मक्खियाँ

63
एक toenail काटने की मशीन के बारे में सोचा बहुत डरावना है। मुझे उम्मीद है कि यह वास्तव में होमवर्क है और न कि एक दर्दनाक त्रासदी होने की प्रतीक्षा कर रहा है।
पीटर रेकोर

43
यहां प्रोग्रामिंग चुनौती उस मशीन को नियंत्रित कर रही है जो टोनल को काटती है ताकि यह लोगों को घायल न करे। यदि कोई प्रोग्रामर उस समस्या को हल करने में सक्षम है, तो निश्चित रूप से वह व्यक्ति दो मिनट में इस समस्या को हल कर सकता है।
मक्खियों

41
मुझे यह तथ्य पसंद है कि यहूदी परंपरा के बारे में एक सवाल (भाषा) अज्ञेय के रूप में टैग किया गया है ... :-)
स्टीव मेलनिकॉफ़

जवाबों:


87

आप बिना किसी प्रतिबंध के सभी संभव टोकन अनुक्रमों को उत्पन्न कर सकते हैं, और फिर सभी अनुक्रमों को फ़िल्टर कर सकते हैं जो कि नियम का उल्लंघन करते हैं। सौभाग्य से, मनुष्य के पास प्रति पैर केवल पांच पैर की उंगलियां हैं *, इसलिए केवल 5 हैं! = 120 अप्रतिबंधित क्रम।

पायथन उदाहरण:

#seq is only valid when consecutive elements in the list differ by at least two.
def isValid(seq):
    for i in range(len(seq)-1):
        a = seq[i]
        b = seq[i+1]
        if abs(a-b) == 1:
            return False
    return True


from itertools import ifilter, permutations
validseqs = ifilter(isValid, permutations([1,2,3,4,5]))
for i in validseqs:
    print i

(1, 3, 5, 2, 4)
(1, 4, 2, 5, 3)
(2, 4, 1, 3, 5)
(2, 4, 1, 5, 3)
(2, 5, 3, 1, 4)
(3, 1, 4, 2, 5)
(3, 1, 5, 2, 4)
(3, 5, 1, 4, 2)
(3, 5, 2, 4, 1)
(4, 1, 3, 5, 2)
(4, 2, 5, 1, 3)
(4, 2, 5, 3, 1)
(5, 2, 4, 1, 3)
(5, 3, 1, 4, 2)

अपने "एक ही क्रम के दोहराए नहीं" नियम को लागू करने के लिए, आप उपरोक्त अनुक्रमों में से केवल चार चुन सकते हैं, और उन्हें वैकल्पिक रूप से उपयोग कर सकते हैं। यहाँ केवल एक ही बात यह है कि यदि आप दो बड़े पैर की उंगलियों को "लगातार" के रूप में गिनते हैं, तो आप दो क्रमों को नहीं चुन सकते हैं जो क्रमशः समाप्त होते हैं और 1 से शुरू होते हैं।

* आप एक नंबर ओफ़्फ़ोटोपेरफ़र चर बनाना चाह सकते हैं, ताकि आप आसानी से इसे बाद में बदल सकें अगर आपका कोई ग्राहक आपकी अपेक्षा से कम पैर की उंगलियों को बाहर निकालता है, या अधिक।


22
आप सही हे! मैंने कभी भी लोगों के साथ पॉलीडेक्टली विचार नहीं किया । उन्हें बाहर करना गलत होगा।
पीटर ओल्सन

1
मूल एल्गोरिथ्म द्वारा कम पैर की उंगलियों के मामले को कवर किया गया है (5 पैर की उंगलियों के लिए स्वीकार्य अनुक्रम 4 पैर की उंगलियों के लिए स्वीकार्य हैं)। यह उन पागल अतिरिक्त पैर की उंगलियों है कि समस्याओं का कारण है;)
मक्खियों

4
बहुत अच्छा समाधान! मैं "एक ही अनुक्रम का कोई दोहराता" दृष्टिकोण हालांकि थोड़ा अलग होगा। बस मशीन को याद रखें कि यह किस अनुक्रम का उपयोग किया था और अगले एक यादृच्छिक (लेकिन एक ही नहीं) का उपयोग करें। यह दूसरे पैर के साथ-साथ नए ग्राहकों के लिए भी काम करता है और यह 4 अनुक्रमों के साथ चिपके रहने की तुलना में अधिक यादृच्छिक है।
जैकब

3
एक को भी पैर की अंगुली से लापता पैर की उंगलियों पर विचार करने की आवश्यकता होगी, जैसे कि 3 पैर की अंगुली गायब। यह समस्या का कारण बनता है, उदाहरण के लिए, तीसरे पैर की अंगुली को हटाने से अब 2 और 4 पैर की उंगलियों को अनुक्रमिक माना जाता है।
cdeszaq

2
एक पैर में केवल 2 पैर की उंगलियों वाले लोगों के बारे में क्या? क्या उन्हें अपने toenails काटने की अनुमति है?
मत्तीसग

26

अनुक्रमों की एक सीमित संख्या है जो आपकी आवश्यकताओं को पूरा करती है।

  1. {1,2,3,4,5} के सभी क्रमांकन उत्पन्न करें। केवल 120 हैं।
  2. उन लोगों को अस्वीकार करें जो आवश्यकताओं को पूरा नहीं करते हैं और शेष सेट (स्थायी रूप से) को स्टोर करते हैं।
  3. बेतरतीब ढंग से दो अलग-अलग दृश्यों को चुनें। याद रखें कि आपने पिछली बार किन लोगों का इस्तेमाल किया था।

संपादित करें: यदि यह वास्तव में पैर की उंगलियों के बारे में नहीं है, लेकिन कुछ यादृच्छिक समस्या के बारे में जहां सेट 5 से अधिक बड़ा हो सकता है, अनुक्रम स्थान बहुत बड़ा हो जाता है और दूसरे चरण पर उसी क्रम को दोहराने की संभावना बहुत छोटी हो जाती है। इसलिए बेतरतीब ढंग से सीक्वेंस पैदा करना और अगर वे मेल खाते हैं तो उन्हें अस्वीकार करना एक अच्छा विचार है। कुछ नियमों के अनुसार रैंडम सीक्वेंस बनाना जैसे "ट्वायस या थ्रोट्स द्वारा हॉप करना, फिर रिक्त स्थान भरना" शायद यादृच्छिक क्रमपरिवर्तन और परीक्षण उत्पन्न करने की तुलना में तेज़ होगा, और ओवरलैप की संभावना अभी भी छोटी होगी यदि "पैर की उंगलियों" की संख्या बड़ी है ।


20

दरअसल, मुझे आपका ओरिजिनल एल्गोरिथम सबसे अच्छा लगता है।

चूंकि 120 में से 14 परमिट काम करते हैं, 120 में से 106 नहीं। इसलिए प्रत्येक चेक में 106/120 विफल होने की संभावना है।

इसका मतलब है कि विफलताओं की अपेक्षित संख्या है:

1*(106/120) + 2*(106/120)^2 + 3*(106/120)^3 + ...

इस अनंत श्रृंखला को योग करने के लिए बहुत मुश्किल नहीं है:

S       = 1*x + 2*x^2 + 3*x^3 + ...

एक्स के माध्यम से गुणा करें:

x*S     =       1*x^2 + 2*x^3 + ...

घटाएँ:

S - x*S = x + x^2 + x^3 + ...

एक्स द्वारा फिर से गुणा करें और फिर से घटाएं:

x*S - x^2*S = x^2 + x^3 + ...
S - 2*x*S + x^2S = x
S*(1-x)^2 = x
S = x/(1-x)^2

चूंकि x = 106/120, S = 64.9।

तो, औसतन आपके लूप को समाधान खोजने के लिए केवल 65 पुनरावृत्तियों की आवश्यकता है

एक हज़ार पुनरावृत्तियों को लेने की संभावना क्या है?

खैर, किसी एकल पुनरावृत्ति को विफल करने की संभावना 104/120 है, इसलिए 1000 पुनरावृत्तियों को विफल करने की संभावना (104/120) ^ 1000 है, जो कि 10 ^ (- 63) की तरह है। यही है, आप इसे अपने जीवनकाल में कभी नहीं देखेंगे, और शायद ब्रह्मांड के जीवनकाल में नहीं।

कोई प्री-कॉम्पट्यूट टेबल, उंगलियों / पैर / हाथों / पैरों की विभिन्न संख्याओं के लिए आसान अनुकूलन, विभिन्न नियमों के लिए आसान अनुकूलन ... क्या पसंद नहीं है? घातीय क्षय एक अद्भुत चीज है।

[अपडेट करें]

वूप्स, मुझे मूल सूत्र गलत मिला ... चूंकि मेरी संभावनाएं 1 से अधिक नहीं हैं। :-)

विफलताओं की अपेक्षित संख्या के लिए सही अभिव्यक्ति है:

0*(14/120) + 1*(106/120)*(14/120) + 2*(106/120)^2*(14/120) + ...

(उदाहरण के लिए, दो विफलताओं को प्राप्त करने के लिए, आपको एक सफलता के बाद दो विफलताओं की आवश्यकता होती है । दो असफलताओं में प्रायिकता (106/120) ^ 2; एक सफलता में संभावना (14/120) होती है, जो वजन बढ़ाने के लिए एक साथ होती हैं। "2" शब्द।)

तो मेरा S (1-x) (यानी, 14/120) के एक कारक से बंद है। विफलताओं की वास्तविक अपेक्षित संख्या सिर्फ x / (1-x) = 106/14 = 7.57 है। तो औसतन इसका समाधान खोजने में केवल 8-9 पुनरावृत्तियों लगते हैं (7.5 विफलताएं प्लस एक सफलता)।

"1000 विफलताओं" मामले के लिए मेरा गणित अभी भी सही है, मुझे लगता है।


1
बॉक्स के बाहर सोचने और समस्या को देखने का एक अलग तरीका देने के लिए +1।
नागवार

9

स्पष्ट: एक आदेश खोजें जो काम करता है, और इसे कठिन कोड। लेकिन मुझे नहीं लगता कि आप ऐसा करना चाहते हैं।

आप जिस तरह से कर रहे हैं, उससे बेहतर तरीके से आप क्रमपरिवर्तन उत्पन्न कर सकते हैं। आपको अस्वीकृति नमूनाकरण करने की आवश्यकता नहीं है। शुरू में क्रमबद्ध क्रमपरिवर्तन (1, 2, .. 5) पर फिशर येट्स फेरबदल का उपयोग करें, और आपके पास एक यादृच्छिक क्रमपरिवर्तन होगा। http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

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


2

वास्तव में यहां कुछ भी नया नहीं है, एक ही समाधान @ केविन पहले से ही पोस्ट किया गया है, लेकिन मुझे यह देखना दिलचस्प है कि यह एक कार्यात्मक भाषा में कैसे अनुवाद करता है। इस मामले में, गणितज्ञ :

Extract[#,Position[Times @@ (Abs@#-1)&/@ Differences/@ #, Except@0, 1][[2 ;;]]]  
         &@ Permutations@Range@5

कुछ स्पष्टीकरण:

Permutations@Range@5 Calculates all permutations of {1, 2, 3, 4, 5}

Differences          Calculate the differences between adjacent elements
                     (we wish to discard all lists containing +1 or -1)

Times @@ (Abs@#-1)   Abs turns the -1s into +1s, and then to zeros by subtracting
                     one, then TIMES multiplies all elements, giving zero when 
                     the original result of "Differences" contained a +1 or a -1

Position ... Except@0 Returns the position of the non zero results

Extract              Returns the original elements according to the calculated 
                     positions

अंतिम परिणाम है:

{{1, 3, 5, 2, 4}, {1, 4, 2, 5, 3}, {2, 4, 1, 3, 5}, {2, 4, 1, 5, 3}, 
 {2, 5, 3, 1, 4}, {3, 1, 4, 2, 5}, {3, 1, 5, 2, 4}, {3, 5, 1, 4, 2}, 
 {3, 5, 2, 4, 1}, {4, 1, 3, 5, 2}, {4, 2, 5, 1, 3}, {4, 2, 5, 3, 1}, 
 {5, 2, 4, 1, 3}, {5, 3, 1, 4, 2}}

संपादित करें

या, समझाने में अधिक कठिन, लेकिन कम:

Reap[ Table[ If[Times @@ (Abs@Differences@i - 1) != 0, Sow@i],
           {i, Permutations@Range@5}]][[2, 1]]

0

इस समस्या में यादृच्छिकता का परिचय देने का वास्तव में कोई कारण नहीं है। केवल 14 सीक्वेंस हैं जो इस समस्या को पूरा करते हैं, और निश्चित रूप से उन सीक्वेंस में से कुछ ऑर्डर करने से आप जिस सौंदर्य बोध को समायोजित करने की कोशिश कर रहे हैं, उसे पूरा करेंगे। इस प्रकार, आपको इस समस्या को केवल 14 से अनुक्रम चुनने के लिए एक एल्गोरिथ्म में कम करना चाहिए, शायद पूर्व-निर्धारित क्रम में।

14 खोजने के लिए एल्गोरिथ्म का जावास्क्रिप्ट कार्यान्वयन:

function swap (a, i, j) {
  var temp = a[i]
  a[i]=a[j]
  a[j]=temp
}

function permute (b, n, a) {
  if (n==4) {
    b.push(a.slice(0)) //copy array
  }
  else {
    for (var i = n; i < 5; i++) {
      swap(a,n,i)
      permute(b, n+1, a)
      swap(a,n,i)
    }
  }
}

var a = [1,2,3,4,5]
var b = []
var c = []

permute(b,0,a)

for (var i = 1; i < b.length-1; i++) {
  var good = true
  for (var j = 0; j < b[i].length; j++) {
    if (Math.abs(b[i][j-1]-b[i][j]) < 2 || Math.abs(b[i][j]-b[i][j+1]) < 2) {
      good = false
    }
  }
  if (good) c.push(b[i].join(''))
}

console.log(c)

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.