একটি ছোট এবং ভারসাম্যপূর্ণ মোবাইল তৈরি করুন


18

আপনাকে একগুচ্ছ ওজন দেওয়া হয় এবং আপনার কাজটি সেই ওজনগুলি ব্যবহার করে একটি ছোট ভারসাম্যপূর্ণ মোবাইল তৈরি করা।

ইনপুটটি অন্তর্ভুক্ত সহ 1 থেকে 9 পর্যন্ত পরিসরের পূর্ণসংখ্যক ওজনের একটি তালিকা। নকল থাকতে পারে।

আউটপুটটি এমন একটি মোবাইলের আসকি ছবি যা ঝুলিয়ে দেওয়া হলে ভারসাম্য বজায় রাখে। উদাহরণস্বরূপ সম্ভবত সেরা প্রদর্শিত:

ইনপুট

3 8 9 7 5

সম্ভাব্য আউটপুট

         |
   +-----+---------+
   |               |
+--+-+        +----+------+
|    |        |           |
8   ++--+     7           5
    |   |
    9   3

প্রদর্শিত হিসাবে আপনি ascii অক্ষর ব্যবহার করতে হবে। অনুভূমিক এবং উল্লম্ব বিভাগগুলি কোনও দৈর্ঘ্যের হতে পারে। মোবাইলের কোনও অংশই মোবাইলের অন্য সংযুক্ত অংশটিকে (অনুভূমিকভাবে বা উলম্বভাবে) স্পর্শ করতে পারে না। কমপক্ষে 1 টি দৈর্ঘ্যের উল্লম্ব বিভাগ থেকে সমস্ত ওজন অবশ্যই ঝুলিয়ে রাখতে হবে এবং এমন একটি উল্লম্ব বিভাগ থাকতে হবে যা থেকে পুরো মোবাইলটি স্তব্ধ থাকে।

একটি মোবাইল আকার মোট সংখ্যা হয় +, -এবং |অক্ষর এটি নির্মাণ করা প্রয়োজন। নিম্ন আকারগুলি আরও ভাল।

আপনি যেমনটি চান সেগমেন্টে অনেকগুলি সংযোগ স্থাপন করতে পারেন। উদাহরণ স্বরূপ:

ইনপুট

2 3 3 5 3 9

সম্ভাব্য আউটপুট

           |
   +---+---+-----------+
   |   |               |
+--+-+ 5               9
|  | |
2  | 3
   |
  +++
  | |
  3 3

বিজয়ী প্রোগ্রামটি এমন একটি যা ইনপুটগুলির পরীক্ষার সেটটির জন্য সর্বনিম্ন মোবাইল আকারের তৈরি করতে পারে। হার্ড-কোডিং প্রতিরোধের জন্য আসল পরীক্ষাটি অতি গোপনীয়, তবে এটি এমন কিছু হবে:

8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 7 7
3 4 4 4 4 5 5 5 5 6 6 6 6 7 7 7 7

জড়িত পদার্থবিজ্ঞানেরও?
আপনি

1
@ এসমার্ক: আমার ধারণা আপনি এটি বলতে পারতেন। শারীরিক প্রতিবন্ধীদের জন্য, total_weight_hung_from_point * distance_of_point_from_pivotপিভট পয়েন্টের উভয় পক্ষের যোগফল অবশ্যই এক হতে হবে।
কীথ র্যান্ডাল

ডায়াগ্রামগুলি পরীক্ষা করা আরও সহজ করার জন্য, এটি তৈরি করুন যাতে একটি বার প্রায় দুটি হাইফেনের সমান হয়? এটি যেমন দাঁড়ায়, আপনার চিত্রগুলি ভারসাম্যের বাইরে চলে।
থমাস হে

উত্তর:


5

পাইথন 2।

আমি একটি প্রতারণার করছি সামান্য বিট:

  • আমি কেবল একটি অনুভূমিক মোবাইল তৈরি করি। আমি একটা অনুভূতি আছে (কিন্তু আমি এটা প্রমাণিত হয় নি) যে দেওয়া অবস্থার অধীনে অনুকূল মোবাইল আসলে সবসময় করে শুধুমাত্র একটি অনুভূমিক আছে। সম্পাদনা: সর্বদা সত্য নয়; 2 2 9 1ন্যাব সহ নীচের মন্তব্যে একটি পাল্টা উদাহরণ পাওয়া গেছে:

    Size 18:                Size 16:
       |                        |
    +-++--+-----+            +--++-+
    | |   |     |            |   | |
    2 9   2     1           -+-  9 1
                            | |
                            2 2
    
  • আমি কেবল বোকা হিংস্র জোর করে:

    1. প্রদত্ত ওজন এলোমেলোভাবে পরিবর্তিত হয়।
    2. একবারে দুটি ওজন মোবাইলে সেরা পজিশনে রাখা হয় যাতে এটি ভারসাম্য বজায় থাকে।
    3. ফলাফলযুক্ত মোবাইলটি আমাদের আগে থাকা যেকোনটির চেয়ে ভাল হলে এটি মনে রাখবেন।
    4. ধুয়ে ফেলুন এবং পুনরাবৃত্তি করুন, অবধি সেকেন্ডের পূর্ব নির্ধারিত সংখ্যার অবধি।

আপনার নমুনা ইনপুট জন্য আমার ফলাফল; প্রত্যেকটি 5 সেকেন্ডের জন্য চালানো হয়েছিল (আমি সচেতন যে এটি ছোটদের পক্ষে হাস্যকর - কেবলমাত্র সমস্ত সম্ভাব্য ক্রমুবর্তনের মধ্য দিয়ে যাওয়া আরও দ্রুত হবে)। মনে রাখবেন যেহেতু একটি এলোমেলো উপাদান রয়েছে, পরবর্তী রানগুলি আরও ভাল বা খারাপ ফলাফল পেতে পারে।

3 8 9 7 5
Tested 107887 mobiles, smallest size 20:
        |
+-+-----+-+--+
| |     | |  |
5 3     7 9  8

2 3 3 5 3 9
Tested 57915 mobiles, smallest size 23:
      |
+--+-++--+-+---+
|  | |   | |   |
3  5 9   3 3   2

8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7
Tested 11992 mobiles, smallest size 50:
                |
+-+-+-+--+-+-+-+++-+-+--+-+-+-+-+
| | | |  | | | | | | |  | | | | |
8 8 8 8  8 8 8 8 8 8 8  7 8 8 8 8

1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 7 7
Tested 11119 mobiles, smallest size 62:
                    |
+-+-+-+-+-+--+-+-+-+++-+-+-+--+-+-+-+-+-+
| | | | | |  | | | | | | | |  | | | | | |
2 7 5 6 6 8  3 2 3 7 9 7 8 1  1 7 9 5 4 4

3 4 4 4 4 5 5 5 5 6 6 6 6 7 7 7 7
Tested 16301 mobiles, smallest size 51:
                |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | | | | |
4 6 5 7 7 4 6 5 3 5 6 4 7 6 7 5 4

কোড (ভার্বোস, কারণ এটি কোড গল্ফ নয়):

import time, random

def gcd(a, b):
    while b > 0:
        a, b = b, a % b
    return a

class Mobile(object):
    def __init__(self):
        self.contents = [None];
        self.pivot = 0;

    def addWeights(self, w1, w2):
        g = gcd(w1, w2)
        m1 = w2 / g
        m2 = w1 / g
        mul = 0
        p1 = -1
        while True:
            if p1 < 0:
                mul += 1
                p1 = mul * m1
                p2 = -mul * m2
            else:
                p1 *= -1
                p2 *= -1
            if self.free(p1) and self.free(p2):
                self.add(w1, p1)
                self.add(w2, p2)
                return

    def add(self, w, pos):
        listindex = self.pivot - pos 
        if listindex < 0:
            self.contents = [w] + (abs(listindex) - 1) * [None] + self.contents
            self.pivot += abs(listindex)
        elif listindex >= len(self.contents):
            self.contents += (listindex - len(self.contents)) * [None] + [w]
        else:
            self.contents[listindex] = w

    def at(self, pos):
        listindex = self.pivot - pos
        if 0 <= listindex < len(self.contents):
            return self.contents[listindex]
        return None

    def free(self, pos):
        return all(self.at(pos + d) is None for d in (-1, 0, 1))

    def score(self):
        return 1 + 2 * len(self.contents) - self.contents.count(None)

    def draw(self):
        print self.pivot * " " + "|"
        print "".join("+" if c is not None or i == self.pivot else "-" for i, c in enumerate(self.contents))
        print "".join("|" if c is not None else " " for c in self.contents)
        print "".join(str(c) if c is not None else " " for c in self.contents)

    def assertBalance(self):
        assert sum((i - self.pivot) * (c or 0) for i, c in enumerate(self.contents)) == 0


weights = map(int, raw_input().split())

best = None
count = 0

# change the 5 to the number of seconds that are acceptable
until = time.time() + 5

while time.time() < until:
    count += 1
    m = Mobile()

    # create a random permutation of the weights
    perm = list(weights)
    random.shuffle(perm)

    if len(perm) % 2:
        # uneven number of weights -- place one in the middle
        m.add(perm.pop(), 0)

    while perm:
        m.addWeights(perm.pop(), perm.pop())

    m.assertBalance() # just to prove the algorithm is correct :)
    s = m.score()
    if best is None or s < bestScore:
        best = m
        bestScore = s

print "Tested %d mobiles, smallest size %d:" % (count, best.score())
best.draw()

@ ন্যাব: 9 এর চেয়ে বেশি ওজন নেওয়া সম্ভব নয়। যেমন 1 9 2 8এটি উত্পন্ন 1-------8+-9--2; আমার মাথার শীর্ষ থেকে আমি আরও ভাল কিছু নিয়ে আসতে পারি না (তবে আমি তার উপর নির্ভর করব না) - আপনার কিছু আছে?
বালফা

1
@ বালফা: কিছুই নয়, আমি আগে মন্তব্য করার সময় সোজা চিন্তা করছিলাম না। আমি কোনও কারণে ভেবেছিলাম যে আপনি তাদের 1-9 এবং 2-8 হিসাবে আটকে রাখতে পারেন, তবে স্পষ্টতই pairs জোড়াটি নিজেরাই ভারসাম্য বজায় রাখে না!
নাবব

ঠিক আছে, এখানে এক যা একাধিক স্তর সহকারে আরও ভাল হতে পারে: 2 2 9 1যেমন (2 + 2) * 3 = 9 + 1 * 3 এর চেয়ে 16 আকারের পরিবর্তে 2-9+--2----118 হবে I'd আমি অনুমান করতে পারি যে এখানে একটি প্রান্তিক (সম্ভবত 5 বা 6) রয়েছে ) যার পরে একটি একক অনুভূমিক সারি সর্বদা অনুকূল থাকে।
ন্যাব

@ নবাব: হ্যাঁ; এটি আসলে একটি ভাল পাল্টা উদাহরণ।
বালফা

@ ন্যাব, 2-2-+9-1ভারসাম্য সহ একটি একক বার , 13 টির স্কোর (4*2+2*2 = 9*1+1*3)। সুতরাং আমি মনে করি না যে এটি একটি ভাল পাল্টা নমুনা।
কিথ র্যান্ডাল 17

1

আচ্ছা এটি একটি পুরানো প্রশ্ন, তবে আমি কেবল এটি শীর্ষ প্রশ্নের ট্যাবে উপস্থিত থাকতে দেখেছি তাই এখানে আমার (অনুকূল) সমাধানটি রয়েছে:

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

int main(int argc, const char *const *argv) {
    if(argc < 2) {
        fprintf(stderr,
            "Balances weights on a hanging mobile\n\n"
            "Usage: %s <weight1> [<weight2> [...]]\n",
            argv[0]
        );
        return 1;
    }
    int total = argc - 1;
    int values[total];
    int maxval = 0;
    for(int n = 0; n < total; ++ n) {
        char *check = NULL;
        long v = strtol(argv[n+1], &check, 10);
        if(v <= 0 || v > INT_MAX || *check != '\0') {
            fprintf(stderr,
                "Weight #%d (%s) is not an integer within (0 %d]\n",
                n + 1, argv[n+1], INT_MAX
            );
            return 1;
        }
        values[n] = (int) v;
        if(values[n] > maxval) {
            maxval = values[n];
        }
    }
    int maxwidth = (int) log10(maxval) + 1;
    for(int n = 0; n < total; ++ n) {
        int width = (int) log10(values[n]) + 1;
        fprintf(stdout,
            "%*s\n%*d\n",
            (maxwidth + 1) / 2, "|",
            (maxwidth + width) / 2, values[n]
        );
    }
    return 0;
}

নিয়মের দিকে নজর দেওয়া থেকে আমি নিশ্চিত যে এটি প্রতারণা করছে না, যদিও এটি মনে হচ্ছে এটি। এটি কেবলমাত্র সমস্ত * সংখ্যাটিকে উলম্ব চেইনে আউটপুট দেবে, মোট ব্যয় 2 * সংখ্যা_of_inputs (যা ন্যূনতম সম্ভব কারণ প্রতিটি সংখ্যার উপরে এটির একটি বার অবশ্যই থাকবে বিন্যাস যাই হোক না কেন)। এখানে একটি উদাহরণ:

./mobile 3 8 9 7 5

উত্পাদন:

|
3
|
8
|
9
|
7
|
5

যা নিখুঁত ভারসাম্য মধ্যে।


আমি মূলত এই চ্যালেঞ্জের প্রবণতায় আরও কিছু চেষ্টা করতে যাচ্ছিলাম, তবে এটি দ্রুত প্রমাণিত হয়েছে যে এটি যেভাবেই হোক এই কাঠামোর কাছে অপ্টিমাইজড হয়ে গেছে


সম্ভবত আমার বিবরণ থেকে পরিষ্কার নয়, তবে আপনি |একটি ওজনের নীচে একটি সংযোগ করতে পারবেন না ।
কিথ র্যান্ডাল

নিবন্ধন করুন মনে রেখে আমি এটি সঠিকভাবে সমাধান করতে যেতে পারে।
ডেভ

1

এখানে এমন একটি সমাধান রয়েছে যা ব্রুটটি ক্ষুদ্রতম একক সারির সমাধানকে বাধ্য করে। কোডটি সমস্ত ক্রিয়াকলাপগুলির উপর পুনরাবৃত্তি করে এবং প্রতিটিটির জন্য কেন্দ্রের গণনা করে। যদি ভর কেন্দ্রে পূর্ণসংখ্যা সমন্বয় থাকে তবে আমরা একটি সমাধান খুঁজে পেয়েছি।

সমস্ত অনুমতি দেওয়ার চেষ্টা করার পরে, আমরা আমাদের বর্তমান ওজন এবং পুনরায় চেষ্টা করে সেটগুলিতে মিশ্রণ (ভর 0 ওজনের সমতুল্য) -এ একটি বিভাগ যুক্ত করি।

প্রোগ্রাম চালানোর জন্য, না python balance.py 1 2 2 4

#!/usr/bin/env python3
import itertools, sys

# taken from http://stackoverflow.com/a/30558049/436792
def unique_permutations(elements):
    if len(elements) == 1:
        yield (elements[0],)
    else:
        unique_elements = set(elements)
        for first_element in unique_elements:
            remaining_elements = list(elements)
            remaining_elements.remove(first_element)
            for sub_permutation in unique_permutations(remaining_elements):
                yield (first_element,) + sub_permutation

def print_solution(cm, values):
    print(('  ' * cm) + '|')
    print('-'.join(['-' if v == 0 else '+'  for v in values]))
    print(' '.join([' ' if v == 0 else '|'  for v in values]))
    print(' '.join([' ' if v == 0 else str(v) for v in values]))



input = list(map(int, sys.argv[1:]))
mass = sum(input)
while True:
    n = len(input)
    permutations = filter(lambda p: p[0] != 0 and p[n-1] != 0, unique_permutations(input))
    for p in permutations:
        cm = 0
        for i in range(n):
            cm += p[i] * i;
        if (cm % mass == 0):
            print_solution(cm//mass, p)
            sys.exit(0)
    input.append(0)

যা এই সেরা সমাধান উত্পাদন করে:

    |
+-+-+-+-+
| | | | |
8 3 9 5 7


    |
+-+-+-+-+-+
| | | | | |
9 2 3 5 3 3

                |
+-+-+-+-+-+-+---+-+-+-+-+-+-+-+-+
| | | | | | |   | | | | | | | | |
8 8 8 8 8 8 8   8 8 8 8 8 8 8 8 7


                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | | | | | | | |
1 1 2 2 3 3 4 4 8 8 5 5 6 6 7 7 7 7 9 9


                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | | | | |
3 4 4 4 4 5 5 5 5 6 7 6 7 7 7 6 6

0

পাইথন ঘ

এটি যে কোনও পরীক্ষার ক্ষেত্রে সর্বোত্তম চেয়ে 1 টির চেয়ে খারাপ কিছু করে না, আমি বিশ্বাস করি এবং এটি 5 সেকেন্ডের মধ্যে করে।

মূলত, আমি একটি একক বার পদ্ধতির ব্যবহার করি। আমি এলোমেলোভাবে ইনপুট অর্ডার করি, তারপরে বারে একবারে ওজন .োকানো। প্রতিটি উপাদানকে হয় এমন অবস্থানে রাখা হয় যা উভয় পক্ষের অতিরিক্ত ওজন হ্রাস করে, বা সেই দৃষ্টিকোণ থেকে দ্বিতীয় সেরা অবস্থান, সময়ের 75% এবং পরবর্তী সময়ের 25% ব্যবহার করে। তারপরে, আমি মোবাইলটি শেষে ভারসাম্যযুক্ত কিনা তা যাচাই করে দেখছি এবং এখন পর্যন্ত পাওয়া সেরা মোবাইলের চেয়ে ভাল। আমি সেরাটি সঞ্চয় করি, তারপরে থামিয়ে 5 সেকেন্ড অনুসন্ধানের পরে এটি মুদ্রণ করে।

ফলাফল, 5 দ্বিতীয় রান:

py mobile.py <<< '3 8 7 5 9'
Best mobile found, score 15:
    |    
+-+-+-+-+
| | | | |
8 7 3 5 9
py mobile.py <<< '2 2 1 9'
Best mobile found, score 13:
   |    
+-++-+-+
| |  | |
1 9  2 2
py mobile.py <<< '2 3 3 5 3 9'
Best mobile found, score 18:
      |    
+-+-+-+-+-+
| | | | | |
2 3 3 5 9 3
py mobile.py <<< '8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7'
Best mobile found, score 49:
                |               
+-+--+-+-+-+-+-+++-+-+-+-+-+-+-+
| |  | | | | | | | | | | | | | |
7 8  8 8 8 8 8 8 8 8 8 8 8 8 8 8
\py mobile.py <<< '1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 7 7'
Best mobile found, score 61:
                    |                   
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+
| | | | | | | | | | | | | | | | | | |  |
1 7 7 5 4 3 1 9 6 7 8 2 2 9 3 7 6 5 8  4
py mobile.py <<< '3 4 4 4 4 5 5 5 5 6 6 6 6 7 7 7 7'
Best mobile found, score 51:
                |                
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | | | | |
4 4 6 7 7 4 5 7 6 6 5 4 6 3 5 5 7

কোড:

import random
import time

class Mobile:
    def __init__(self):
        self.contents = {}
        self.lean = 0

    def usable(self, loc):
        return not any(loc + k in self.contents for k in (-1,0,1))
    def choose_point(self, w):
        def goodness(loc):
            return abs(self.lean + w * loc)
        gl = sorted(list(filter(self.usable,range(min(self.contents.keys() or [0]) - 5,max(self.contents.keys() or [0]) + 6))), key=goodness)
        return random.choice((gl[0], gl[0], gl[0], gl[1]))

    def add(self, w, loc):
        self.contents[loc] = w
        self.lean += w*loc

    def __repr__(self):
        width = range(min(self.contents.keys()), max(self.contents.keys()) + 1)
        return '\n'.join((''.join(' ' if loc else '|' for loc in width),
                          ''.join('+' if loc in self.contents or loc == 0 else '-' for loc in width),
                          ''.join('|' if loc in self.contents else ' ' for loc in width),
                          ''.join(str(self.contents.get(loc, ' ')) for loc in width)))

    def score(self):
        return max(self.contents.keys()) - min(self.contents.keys()) + len(self.contents) + 2

    def my_score(self):
        return max(self.contents.keys()) - min(self.contents.keys()) + 1

best = 1000000
best_mob = None
in_weights = list(map(int,input().split()))
time.clock()
while time.clock() < 5:
    mob = Mobile()
    for insert in random.sample(in_weights, len(in_weights)):
        mob.add(insert, mob.choose_point(insert))
    if not mob.lean:
        if mob.score() < best:
            best = mob.score()
            best_mob = mob

print("Best mobile found, score %d:" % best_mob.score())
print(best_mob)

এই সমাধানগুলির মধ্যে কেবলমাত্র আমি মনে করি যে সাবওটিটিমাল হ'ল এটি দীর্ঘতম, যার মধ্যে এই সমাধান রয়েছে, যা আমি 10 মিনিটের দৌড়ের পরে পেয়েছি:

Best mobile found, score 60:
                   |                   
+-+-+-+-+-+-+-+-+-+++-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | | | | | | | |
3 2 9 4 7 8 1 6 9 8 7 1 6 2 4 5 7 3 5 7
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.