कुछ सेब की छंटाई करें!


11

मुसीबत

कल्पना कीजिए कि 7 बाल्टियाँ पंक्तिबद्ध थीं। प्रत्येक बाल्टी में अधिकतम 2 सेब हो सकते हैं। 1 के माध्यम से 1 के माध्यम से लेबल किए गए 13 सेब हैं। उन्हें 7 बाल्टी के बीच वितरित किया जाता है। उदाहरण के लिए,

{5,4}, {8,10}, {2,9}, {13,3}, {11,7}, {6,0}, {12,1}

जहां 0 खाली जगह का प्रतिनिधित्व करता है। प्रत्येक बकेट के भीतर सेब दिखाई देने वाला क्रम प्रासंगिक नहीं है (जैसे {5,4} {4,5} के बराबर)।

आप किसी भी सेब को एक बाल्टी से एक बगल की बाल्टी में स्थानांतरित कर सकते हैं, बशर्ते दूसरे सेब के लिए गंतव्य बाल्टी में कमरा हो। प्रत्येक चाल को उस सेब की संख्या से वर्णित किया जाता है जिसे आप स्थानांतरित करना चाहते हैं (जो असंदिग्ध है क्योंकि केवल एक खाली जगह है)। उदाहरण के लिए, इस कदम को लागू करना

7

इसके बाद के संस्करण की व्यवस्था में परिणाम होगा

{5,4}, {8,10}, {2,9}, {13,3}, {11,0}, {6,7}, {12,1}

उद्देश्य

एक प्रोग्राम लिखें जो एसटीडीआईएन से एक व्यवस्था पढ़ता है और इसे निम्नलिखित व्यवस्था में क्रमबद्ध करता है

{1,2}, {3,4}, {5,6}, {7,8}, {9,10}, {11,12}, {13,0}

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

13, 7, 6, ...

आपका स्कोर निम्नलिखित व्यवस्थाओं को हल करने के लिए आवश्यक चालों की संख्या के योग के बराबर है:

{8, 2}, {11, 13}, {3, 12}, {6, 10}, {4, 0}, {1, 7}, {9, 5}
{3, 1}, {6, 9}, {7, 8}, {2, 11}, {10, 5}, {13, 4}, {12, 0}
{0, 2}, {4, 13}, {1, 10}, {11, 6}, {7, 12}, {8, 5}, {9, 3}
{6, 9}, {2, 10}, {7, 4}, {1, 8}, {12, 0}, {5, 11}, {3, 13}
{4, 5}, {10, 3}, {6, 9}, {8, 13}, {0, 2}, {1, 7}, {12, 11}
{4, 2}, {10, 5}, {0, 7}, {9, 8}, {3, 13}, {1, 11}, {6, 12}
{9, 3}, {5, 4}, {0, 6}, {1, 7}, {12, 11}, {10, 2}, {8, 13}
{3, 4}, {10, 9}, {8, 12}, {2, 6}, {5, 1}, {11, 13}, {7, 0}
{10, 0}, {12, 2}, {3, 5}, {9, 11}, {1, 13}, {4, 8}, {7, 6}
{6, 1}, {3, 5}, {11, 12}, {2, 10}, {7, 4}, {13, 8}, {0, 9}

हां, इनमें से प्रत्येक व्यवस्था का एक समाधान है।

नियम

  • आपका समाधान बहुपदीय समय में प्रति चाल बाल्टी की संख्या में चलना चाहिए। बात यह है कि चतुर उत्तराधिकारियों का उपयोग करना है।
  • सभी एल्गोरिदम को नियतात्मक होना चाहिए।
  • एक टाई की स्थिति में, सबसे छोटी बाइट गिनती जीत जाती है।

2
गंतव्य को निरूपित करने का क्या मतलब है जब केवल एक स्थान है जिसे आप एक सेब को स्थानांतरित कर सकते हैं?
जॉन ड्वोरक

यदि उचित समय में मेरा जानवर बल समाधान चलता है तो क्या होगा? केवल 700M राज्य हैं - मिनटों के मामले में आसानी से गणना करने योग्य। "समय की उचित मात्रा" को परिभाषित करें।
जॉन ड्वोरक

@JDDvorak प्रति "क्या बात है" - अच्छी कॉल। मेरे साथ ऐसा नहीं हुआ था। मैं उचित परिभाषित कर रहा हूँ कि समाधान को बल देने के लिए आवश्यक समय से कम हो;)
Orby

क्या "उचित" की आपकी परिभाषा का अर्थ है कि हमें पहले जानवर-बल समाधान को लागू करना चाहिए, फिर कुछ भी जो तेजी से मायने रखता है?
जॉन डेवोरक

क्या बाल्टी का अंतिम आदेश महत्वपूर्ण है?
AMK

जवाबों:


4

स्कोर: 448

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

#1: 62     #6: 40
#2: 32     #7: 38
#3: 46     #8: 50
#4: 50     #9: 54
#5: 40    #10: 36

Total score: 448 moves

कोड को बहुत अधिक रखा जा सकता है, लेकिन कोड की बेहतर गुणवत्ता अतिरिक्त उत्तरों को प्रेरित करेगी।

सी ++ (501 बाइट्स)

#include <cstdio>
#define S(a,b) a=a^b,b=a^b,a=a^b;
int n=14,a[14],i,j,c,g,p,q;
int l(int x){for(j=0;j<n;++j)if(a[j]==x)return j;}
int sw(int d){
    p=l(0);q=p+d;
    if(a[q]*d>a[q^1]*d)q^=1;
    printf("%d,", a[q]);
    S(a[q],a[p])
}
int main(){
    for(;j<n;scanf("%d", a+j),j++);
    for(;++i<n;){
        c=l(i)/2;g=(i-1)/2;
        if(c-g){
            while(l(0)/2+1<c)sw(2);
            while(l(0)/2>=c)sw(-2);
            while(l(i)/2>g){sw(2);if(l(i)/2>g){sw(-2);sw(-2);}}
        }
    }
}

आगे के सुधार सी पर स्विच हो सकते हैं और बड़े मूल्यों से नीचे की ओर शुरू करके स्कोर को कम करने की कोशिश कर सकते हैं (और वे अंततः दोनों समाधानों का संयोजन कर रहे हैं)।


1
आपके कोड का एक विकल्प पहले से ही C प्रोग्राम बनाता है। विशेष रूप से, यह केवल पहली पंक्ति को हटाने के द्वारा C में काम कर सकता है।
feersum

@ फैर्सम यू आर राइट। शुरुआत में, मेरे पास अधिक सी ++ विशिष्ट कोड था, लेकिन उसके बाद सी को ध्यान में रखते हुए, ऐसा लगता है कि मुझे इससे छुटकारा मिल गया।
यासेन

क्या आप यह निर्दिष्ट कर सकते हैं कि आपने अपने समाधान में इनपुट प्रारूप को बदल दिया है ताकि यह उन लोगों के लिए और अधिक स्पष्ट हो सके जो इसे सत्यापित करने का प्रयास करते हैं?
ओर्बी

2

सी, 426 448

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

#1: 62    #6: 40
#2: 32    #7: 38
#3: 46    #8: 50
#4: 50    #9: 54
#5: 40    #10: 36

यह बिना ब्रेसेस या कॉमा के इनपुट लेता है, जैसे

8 2 11 13 3 12 6 10 4 0 1 7 9 5

यहाँ 423 बाइट्स में आने वाले गोल्फ कोड को कुछ अनावश्यक न्यूलाइन्स की गिनती के लिए रखा गया है (शायद इसे और अधिक गोल्फ किया जा सकता है, लेकिन मुझे उम्मीद है कि यह स्कोर पिट जाएगा)

#define N 7
#define F(x,y) for(y=0;y<N*2;y++)if(A[y]==x)break;
#define S(x,y) x=x^y,y=x^y,x=x^y;
#define C(x,y) ((A[x*2]==y)||(A[x*2+1]==y))
A[N*2],i,j,d,t,b,a,n,s,v,u,w,g;main(){for(;i<N*2;i++)scanf("%d",A+i);g=1;while
(!v){F(0,i);b=i/2;F(g,u);w=u/2;d=b<w?1:-1;n=(b+d)*2;a=(b+d)*2+1;if(A[n]>A[a])
S(n,a);t=d-1?a:n;printf("%d,",A[t]);S(A[i],A[t]);while(C((g-1)/2,g))g++;v=1;for
(j=0;j<N*2;j++)if(!C(j/2,(j+1)%(N*2)))v=0;}}

और अनगोल्ड कोड, जो स्कोर भी प्रिंट करता है:

#include <stdio.h>
#include <stdlib.h>

#define N 7

int apples[N*2];

int find(int apple)
{
    int i;
    for (i = 0; i < N*2; i++) {
        if (apples[i] == apple)
            return i;
    }    
}

void swap(int i, int j)
{
    int temp;
    temp = apples[i];
    apples[i] = apples[j];
    apples[j] = temp;
}

int contains(int bucket, int apple)
{
    if ((apples[bucket * 2] == apple) || (apples[bucket * 2 + 1] == apple))
        return 1;
    return 0;
}

int is_solved()
{
    int i, j;
    for (i = 0; i < N * 2; i++) {
        j = (i + 1) % (N * 2);
        if (!contains(i / 2, j))
            return 0;
    }
    return 1;
}

int main()
{
    int i, j, dir, bucket, max, min, score;
    int target_i, target_bucket, target;

    /* Read the arrangement */
    for (i = 0; i < N*2; i++) {
        scanf("%d ", apples + i);
    }

    target = 1;
    while (1) {

        i = find(0);
        bucket = i / 2;
        target_i = find(target);
        target_bucket = target_i / 2;

        /* Change the direction of the sort if neccesary */
        if (bucket < target_bucket) dir = 1;
        else dir = -1;

        /* Find the biggest and smallest apple in the next bucket */
        if (apples[(bucket + dir) * 2] < apples[(bucket + dir) * 2 + 1]) {
            min = (bucket + dir) * 2;
            max = (bucket + dir) * 2 + 1;
        } else {
            min = (bucket + dir) * 2 + 1;
            max = (bucket + dir) * 2;
        }

        /* If we're going right, move the smallest apple. Otherwise move the
           biggest apple */
        if (dir == 1) {
            printf("%d, ", apples[min]);
            swap(i, min);
            score++;
        } else {
            printf("%d, ", apples[max]);
            swap(i, max);
            score++;
        }

        /* Find the next apple to sort */
        while (contains((target - 1) / 2, target))
            target++;

        /* If we've solved it then quit */
        if (is_solved())
            break;
    }
    printf("\n");
    printf("%d\n", score);
}

2

अजगर 3 - 121

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

इनपुट एक प्रकार की इन्टस है, जिसमें पहली इंट में बकेट की संख्या है।

उदाहरण के लिए, # 8 के लिए (यह मेरी मशीन पर चलने में बहुत लंबा समय लेता है, अन्य लोग सेकंड में समाप्त होते हैं):

c:\python33\python.exe apples.py 7 3 4 10 9 8 12 2 6 5 1 11 13 7 0

यहाँ परीक्षण सेट पर परिणाम हैं: # 1: 12, # 2: 12, # 3: 12, # 4: 12, # 5: 11, # 6: 11, # 7: 10, # 8: 14, # 9: 13, # 10: 14

यहाँ कोड है:

import sys    

BUCKETS = int(sys.argv[1])    

# cleans a state up so it is in order
def compressState(someState):
  for i in range(BUCKETS):
    if(someState[2*i] > someState[2*i + 1]):
      temp = someState[2*i]
      someState[2*i] = someState[2*i + 1]
      someState[2*i + 1] = temp
  return someState    

state = compressState([int(x) for x in sys.argv[2:]])
print('Starting to solve', state)
WINNINGSTATE = [x for x in range(1, BUCKETS*2 - 1)]
WINNINGSTATE.append(0)
WINNINGSTATE.append(BUCKETS*2 - 1)
maxDepth = 1
winningMoves = []
triedStates = {}    

# does a depth-first search
def doSearch(curState, depthLimit):
  if(curState == WINNINGSTATE):
    return True
  if(depthLimit == 0):
    return False
  myMoves = getMoves(curState)
  statesToVisit = []
  for move in myMoves:
    newState = applyMove(curState, move)
    tns = tuple(newState)
    # do not visit a state again unless it is at a higher depth (more chances to win from it)
    if(not ((tns in triedStates) and (triedStates[tns] >= depthLimit))):
      triedStates[tns] = depthLimit
      statesToVisit.append((move, newState[:], stateScore(newState)))
  statesToVisit.sort(key=lambda stateAndScore: stateAndScore[2])
  for stv in statesToVisit:
    if(stv[2] > statesToVisit[0][2]):
      continue
    if(doSearch(stv[1], depthLimit - 1)):
      winningMoves.insert(0, stv[0])
      return True
  return False    

# gets the moves you can make from a given state
def getMoves(someState):
  # the only not-allowed moves involve the bucket with the 0
  allowedMoves = []
  for i in range(BUCKETS):
    if((someState[2*i] != 0) and (someState[2*i + 1] != 0)):
      allowedMoves.append(someState[2*i])
      allowedMoves.append(someState[2*i + 1])
  return allowedMoves    

# applies a move to a given state, returns a fresh copy of the new state
def applyMove(someState, aMove):
  newState = someState[:]
  for i in range(BUCKETS*2):
    if(newState[i] == 0):
      zIndex = i
    if(newState[i] == aMove):
      mIndex = i
  if(mIndex % 2 == 0):
    newState[mIndex] = 0
  else:
    newState[mIndex] = newState[mIndex-1]
    newState[mIndex-1] = 0
  newState[zIndex] = aMove
  if((zIndex % 2 == 0) and (newState[zIndex] > newState[zIndex+1])):
    newState[zIndex] = newState[zIndex+1]
    newState[zIndex+1] = aMove
  return newState    

# a heuristic for how far this state is from being sorted
def stateScore(someState):
  return sum([1 if someState[i] != WINNINGSTATE[i] else 0 for i in range(BUCKETS*2)])    

# go!
while(True):
  triedStates[tuple(state)] = maxDepth
  print('Trying depth', maxDepth)
  if(doSearch(state, maxDepth)):
    print('winning moves are: ', winningMoves)
    break
  maxDepth += 1

मैंने इसे ऊपर उठाया है क्योंकि यह इष्टतम समाधानों को देखने के लिए उपयोगी है, लेकिन ध्यान दें कि यह बहुपदीय समय में बाल्टी की संख्या में नहीं चलता है जैसा कि प्रश्न द्वारा आवश्यक है। मेरा मानना ​​है कि कोई भी एल्गोरिथ्म जो एक इष्टतम समाधान (सामान्य रूप से) का उत्पादन करता है, बहुपद समय में चल सकता है।
ओर्बी

पहली परीक्षण समस्या के लिए, आपका कार्यक्रम 10, 8, 1, 12, 6, 7, 11, 3, 5, 13, 4, 9 उत्पन्न करता है, जो एक वैध समाधान नहीं है। मुझे लगता है कि आपको सवाल गलत लग सकता है। नोटिस में कहा गया है कि "आप किसी भी सेब को एक बाल्टी से एक बगल की बाल्टी में ले जा सकते हैं" यानी बाल्टी को दायीं या बायीं तरफ (एक मनमाना बाल्टी नहीं)।
Orby

ओह, मैं पूरी तरह से आसन्न प्रतिबंध से चूक गया! पोस्ट करने के बाद मुझे यह संदेह था कि रनिंग टाइम प्रतिबंध का भी उल्लंघन किया गया था। मैं 100% निश्चित नहीं था क्योंकि मैं इसे लिख रहा था, क्योंकि दोहराया राज्यों से बचने के गतिशील प्रोग्रामिंग तत्व ने मुझे भ्रमित किया। अपवोट के लिए धन्यवाद भले ही यह दो मायने रखता है; यह एक मजेदार पहेली है और मैं देखूंगा कि क्या मैं बेहतर, मान्य उत्तर दे सकता हूं।
आरटी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.