Задача Кода. Создайте Решатель Задачи «N Шариков На Весах».

  • Автор темы Websanati
  • Обновлено
  • 23, Oct 2024
  • #1

Задача о двенадцати шарах — это известная задача, в которой вам даны двенадцать шаров, один из которых разного веса, но вы не знаете, тяжелее или легче другие шары. Используя всего три взвешивания на двусторонних весах, можно найти шар разного веса, и определить, тяжелее он или легче.

Ваша задача — создать программу, которая выполняет следующие действия:

  • Принять несколько шаров 2N to be compared, from N к 930 . (In the traditional problem, N .)

  • Создайте два списка чисел, обозначающих шары, которые нужно разместить на каждой стороне весов. С каждой стороны необходимо разместить одинаковое количество шариков.

  • Примите входные данные, указывающие, тяжелее ли левая сторона шкалы, тяжелее правая сторона или равны ли две стороны (это можно представить любым способом: например, N = 12 для левого, N = 12 на равных, x for right, or N for left, 100 for right, and 8 для равных) и в ответ либо составить еще одну пару списков шаров, которые нужно взвесить, либо угадать, какой шар другой и тяжелее он или легче.

Ваш результат представляет собой сумму максимум количество взвешиваний для каждого значения N from 3 к 2 that it took to figure out the right answer for 1 шары по вашему алгоритму (каждый случай «шара 1 is heavier/lighter" must be tested). Lowest score wins.

Например, если для 0 , your algorithm managed to get 3 weighings for every case except "ball 8 is heavy" where it took 4 weighings, your score for -1 равно 4. Если ваш максимальный балл составил 10 взвешиваний за каждое N = 12 from 8 to 100, your final score would be 100 .

Ваш алгоритм должен возвращать правильный ответ для всех возможных тестовых случаев (для любого 8 , there are N возможных тестовых случаев, что в общей сложности составляет 10 044). Кроме того, размер исходного кода вашего решения не может превышать 51 200 байт (50 КБ).

#код-задача #головоломка-решатель

Websanati


Рег
30 Nov, 2013

Тем
78

Постов
186

Баллов
626
  • 26, Oct 2024
  • #2

Ткл, 455 426

 
 
 
 
 #recursive weighing method
def weigh(list, heavy):

l=len(list)

if l==1:

return list[0]

list1=list[0::3]

list2=list[1::3]

list3=[]

if len(list1)>len(list2):

list3.append(list1.pop())

print("%s|%s"%(list1,list2))

side=input("(0,1,2) for (neither,left,right) is %s"%heavy)

if side==2:

return weigh(list2, heavy)

if side:

return weigh(list1, heavy)

for i in list[2::3]:

list3.append(i)

return weigh(list3, heavy)
#End Function, begin rest of program
#This part of the program is long because I need to determine whether the odd ball
#is heavy or light
list=range(input("Number of Balls: "))
#split the list into 3
list1=list[0::3]
list2=list[1::3]
list3=list[2::3]
#make list3 the odd man out, if there is one
if len(list1)>len(list2):

list1,list3=list3,list1
print("%s|%s"%(list1,list2))
side=input("(0,1,2) for (neither,left,right) is heavier")
#if side==0
if not side:

heavy="heavier"

if len(list3)<len(list1):

list3.append(list2.pop())

elif len(list3)>len(list1):

list2.append(list3.pop())

print("%s|%s"%(list1,list3))

side2=input("(0,1,2) for (neither,left,right) is heavier")

if side2==1:

heavy="lighter"

print("%s: %s"%(weigh(list3, heavy),heavy))
else:

if side==2:

list1,list2=list2,list1

if len(list3)!=len(list2):

if len(list3)<len(list1):

list3.append(list1.pop())

if len(list3)>len(list2):

list1.append(list3.pop())

print("%s|%s"%(list2,list3))

side2=input("(0,1,2) for (neither,left,right) is heavier")

if not side2:

print("%s: heavier"%weigh(list1, "heavier"))

else:

possibleAns = list3.pop()

list3.append(list1.pop())

print("%s|%s"%(list2,list3))

side3=input("(0,1,2) for (neither,left,right) is heavier")

if not side3:

print("%s: heavier"%possibleAns)

else:

print("%s: lighter"%weigh(list2,"lighter"))

else:

print("%s|%s"%(list2,list3))

side2=input("(0,1,2) for (neither,left,right) is heavier")

if not side2:

print("%s: heavier"%weigh(list1,"heavier"))

else:

print("%s: lighter"%weigh(list2,"lighter"))
 

Независимо от того, что вы выберете, следующий вопрос всегда один и тот же.

 

KathrynMarm


Рег
18 Apr, 2014

Тем
65

Постов
199

Баллов
534
  • 26, Oct 2024
  • #3

Python — 4929 взвешиваний

Набросок тривиального решения, стоящего на последнем месте:

// Weigh function function weigh(a,b) { weigh.count++; var len = a.length; if (len !== b.length) { throw({name:"NotEqual",message:"Can not compare."}); } var wa, wb; wa = wb = 0; for(var i = 0; i < len; i++) { wa += a[i]; wb += b[i]; } return (wa === wb) ? 0 : (wa > wb) ? -1 : 1; } weigh.count = 0; function findOddBall(arr) { var s = [arr]; var isHeavy = true; var priorR = null; var left = null; var right = null; //console.log(arr); while(k=s.pop()) { //console.log('isHeavy:' + isHeavy + ' ' + k.slice(0)); var len = k.length; if (len === 1) { if (priorR !== 0) { return [k[0], isHeavy] } var r = priorR = weigh([left[0]],k); if (r !== 0) { // we know that the oddball is one of these.. but which one? // we need to do a final comparison with the right side. priorR = r; r = weigh([right[0]],k); if (r === 0) { // prior heavy/light isHeavy = (priorR === -1)?true:false; return [left[0],isHeavy] } else if(r === 1) { return [k[0], true] // heavy } return [k[0], false] //light } continue; } x = (len % 2 === 0) ? len : len-1; right = k.splice(0,x); if(k.length !== 0) { s.push(k); // remainder } left = right.splice(0,x/2); var r = priorR = weigh(left, right); if (r === 0) { // We chose a normal side. Test the other side. isHeavy = !isHeavy; } else if ((r === -1 && isHeavy)|| (r === 1 && !isHeavy)) { s.push(right); s.push(left); // left is heavier / lighter } else if((r === 1 && isHeavy)|| (r === -1 && !isHeavy)) { s.push(left); s.push(right); // right is heavier / lighter } } throw({name:"NotFound",message:"Can not find oddball."}); } function main() { var total = 0; var variations = 0; var start = 8; var end = 100; function test(isHeavy) { var normal = (isHeavy) ? 0 : 1; var oddball = (isHeavy) ? 1 : 0; var score = 0; var base = []; for (var i=0; i < start;i++) { base.push(normal); } for (var i=start; i <=end; i++) { base.push(normal); var max = 0; for (var j=0; j<i; j++) { // try each placement var arr = base.slice(0); arr[j]=oddball; variations++; weigh.count = 0; // reset the scale var result = findOddBall(arr); if (result[0] !== oddball || result[1] !== isHeavy) { console.log(i); throw({name:"WrongAnswer",message:"Returned wrong answer."}); } if (weigh.count > max) { max = weigh.count; } //console.log(variations); } total+=max; } } test(true); test(false); console.log(variations); console.log(total); } main();

Это решение просто непрерывно помещает первый шар с левой стороны, а другой шар с правой стороны, пока не обнаружится, что либо первый шар имеет другой вес, либо один из остальных.

Это занимает максимум proc weight balls { if {[llength $balls] == 1 || [llength $balls] == 0} {return [lindex $balls 0]} set len [expr {([llength $balls]+1)/3}] set a [lrange $balls 0 ${len}-1] set b [lrange $balls $len [expr {$len*2-1}]] set c [lrange $balls [expr {$len*2}] end] puts "$a VS $b (0 = left side is havier, 1 = right side is havier, 2 = equal)" tailcall weight [lindex [list $a $b $c] [gets stdin]] } puts "Number of balls" for {set i 1} \$i<=[gets stdin] {incr i} {lappend balls $i} puts [weight $balls] weighings for N-1 шары (в любом случае, если последний шар другой, N weighings are required), which is 4929 weighings total.

 

Munsjuty


Рег
30 Oct, 2006

Тем
82

Постов
212

Баллов
632
  • 26, Oct 2024
  • #4

Ткл, 369

N-1

Алгоритм очень прост: (попробуйте) разделить список на 3 равные части (последние могут быть разными), взвесить первые 2 и сделать это снова для выбранной части (если они равны, используйте третью часть)

 

Piter_Pen


Рег
28 Nov, 2007

Тем
85

Постов
191

Баллов
636
  • 26, Oct 2024
  • #5

JavaScript 1281

N = input("Enter number of balls: ") a = 1 b = 2 print a, "|", b first_result = input("Is left side heavy (1), right side heavy (2), or both equal (3)? ") while(True): b += 1 print a, "|", b result = input("Is left side heavy (1), right side heavy (2), or both equal (3)?") if result == first_result and result != 3: # ball 1 is our culprit. print "Ball 1 is %s." % ("heavier" if first_result == 1 else "lighter") break elif result != first_result and result == 3: # ball 2 is our culprit. print "Ball 2 is %s." % ("heavier" if first_result == 2 else "lighter") break elif result != first_result and first_result == 3: # ball b is our culprit. print "Ball %d is %s." % (b, "heavier" if result == 2 else "lighter") break ||answer||

Питон - ?

proc weight n { set num [expr {int(log($n*2-1)/log(3))+1}] set len [expr {$n/3}] set pn 0 set pri {2 5 7 11 13 17 19 23 29 31 37 41 43 59 61 67} for {set i 0} {$i < $num} {incr i} { set a {} while {![llength $a]} { set a {} set b {} set c {} while { ($n+1)%[lindex $pri $pn]==0 ||($n-1)%[lindex $pri $pn]==0 ||$n%[lindex $pri $pn]==0} {incr pn; puts $pn} set cpn [lindex $pri $pn] for {set j 0} {$j < $len} {incr j} { set tmp [expr {($j*$cpn)%$n}] lappend a $tmp incr tmp 1 if {$tmp in $a} {set a {}; break} lappend b $tmp } incr pn } for {set j 0} {$j < $n} {incr j} { if {$j ni $a && $j ni $b} {lappend c $j} } puts "[lsort -integer $a] VS [lsort -integer $b] - Which is havier? -1 = left, 0 = equal, 1 = right" set idx [expr {[gets stdin] + 1}] if {$i == 0} { if {$idx == 1} { set p1 $c set p2 $c } elseif {$idx == 0} { set p1 $a set p2 $b } else { set p1 $b set p2 $a } } else { set lists [list $a $c $b] set p1 [lmap it [lindex $lists $idx] {if {$it ni $p1} continue; set it}] set p2 [lmap it [lindex $lists 2-$idx] {if {$it ni $p2} continue; set it}] } } if {[llength $p1]} {puts "Result $p1"} {puts "Result $p2"} } puts "Number of balls?" weight [gets stdin]

Эта программа работает, разделяя шары на три списка, сравнивая их, чтобы определить, какой из них тяжелее или легче, а затем рекурсивно находит его.

 

Nikesneacp80


Рег
20 Mar, 2014

Тем
63

Постов
189

Баллов
524
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно