Kontes menjatuhkan telur

8

Tantangan Anda:

Anda berada di lantai 0 sebuah gedung tinggi tanpa batas. Di lantai mana pun, Anda bisa berjalan ke jendela dan menjatuhkan sebutir telur. Tujuan Anda adalah untuk mengetahui lantai tertinggi yang dapat ditahan telur tanpa pecah. Namun, Anda memiliki maksimal 3 butir telur untuk digunakan, tetapi Anda harus meminimalkan jumlah percobaan.

Secara formal:

  1. Anda diberi fungsi f(n)yang mengembalikan bool(n <= X)untuk sesuatu yang tidak dikenalX , di mana0 <= X
  2. Anda harus mengembalikan nilai X (tanpa mengaksesnya langsung)
  3. f(n)harus hanya mengembalikan Falsewaktu maksimum 3(dalam satu test case). Jika kembaliFalse lebih dari itu, maka jawaban Anda didiskualifikasi.

Batasan

Skor Anda adalah jumlah total panggilan yang Anda lakukan f(n) (dalam kasus uji di bawah)

Jika mau, Anda dapat mengabaikan fungsi, dan hanya "mensimulasikan" situasi di atas. Namun , algoritma pemecahan Anda harus tahu apa-apa X.

Algoritme Anda seharusnya tidak memberikan kode pada kasus pengujian, atau maksimum X. Jika saya ingin membuat ulang angka, atau menambahkan lebih banyak, program Anda harus dapat menanganinya (dengan skor yang sama).

Jika bahasa Anda tidak mendukung integer presisi sewenang-wenang, maka Anda dapat menggunakan longtipe data. Jika bahasa Anda tidak mendukung, maka Anda kurang beruntung.

Kasing uji n dihasilkan menggunakan yang berikut ini:

g(n) = max(g(n-1)*random(1,1.5), n+1), g(0) = 0, atau sekitar 1.25^n

Kasus uji:

0,1,2,3,4,6,7,8,10,14,15,18,20,27,29,40,57,61,91,104,133,194,233,308,425,530,735,1057,1308,1874,2576,3162,3769,3804,4872,6309,7731,11167,11476,15223,15603,16034,22761,29204,35268,42481,56238,68723,83062,95681,113965,152145,202644,287964,335302,376279,466202,475558,666030,743517,782403,903170,1078242,1435682,1856036,2373214,3283373,4545125,6215594,7309899,7848365,8096538,10409246,15103057,20271921,22186329,23602446,32341327,33354300,46852754,65157555,93637992,107681394,152487773,181996529,225801707,324194358,435824227,579337939,600264328,827690923,1129093889,1260597310,1473972478,1952345052,1977336057,2512749509,3278750235,3747691805,5146052509

Ini adalah , dan orang dengan skor terendah menang!

Nathan Merrill
sumber
2
Terkait (lihat juga pertanyaan yang ditautkan dalam komentar saya untuk yang itu).
Peter Taylor
1
Pertanyaan terkait pada Puzzling SE (tetapi juga dengan jumlah lantai maksimum).
Martin Ender
8
Jika saya menjatuhkan satu telur dari jendela lantai nol di bangunan mana pun, saya cukup yakin itu akan hancur. Masalah terpecahkan 😉
Trauma Digital
5
@NathanMerrill Point adalah, ini pada dasarnya tidak berguna karena kita tidak bisa tahu apa-apa tentang seberapa besar kemungkinan masing-masing x adalah ketika Anda menolak untuk menentukan apa yang dapat kita asumsikan tentang n . Tidak mungkin menulis jawaban yang dioptimalkan jika kami tidak tahu semua parameter tentang bagaimana Anda menjalankan penilaian. Jika Anda memberi tahu kami "kode Anda dijalankan pada 100 kasus uji dari n = 0 hingga 99," itu akan menjadi jaminan yang berguna. Atau jika Anda membuat g independen dari n .
FUZxxl
11
Voting to close: Tanpa distribusi probabilitas untuk cukup mereplikasi proses penilaian, kriteria yang menang tidak objektif.
FUZxxl

Jawaban:

8

Javascript, 442859 442857 74825 panggilan

function findFloor(f){
    var max = 1;
  var min = 0;

  //First egg.
  var n = 1;
  while (f(max)) {
    min = max;
    n += 1;
    max = tetrahedral(n);
  }

  if (max <= min + 1){
    return min;
  }

  //Second egg.
  do {
    var range = max - min;
    var floor = min + reverseTriangle(range);
    var smashed = !f(floor);
    if (smashed) {
        max = floor;
    } else {
        min = floor;
    }
  } while (!smashed && max > min + 1);

  if (max <= min + 1){
    return min;
  }

  //Third egg.
  while (max > min + 1){
    var floor = min + 1;
    var smashed = !f(floor);
    if (smashed) {
        max = floor;
    } else {
        min = floor;
    }
    if (smashed) {
        break;
    }
  }

  return min;

}

function reverseTriangle(x) {
    return Math.ceil((-1 + Math.sqrt(1 + 8 * x)) / 2);
}

function tetrahedral(n) {
    return n * (n + 1) * (n + 2) / 6;
}

Tes di sini

Skor untuk setiap kasus uji individual:

0: 1, 1: 4, 2: 4, 3: 3, 4: 5, 6: 6, 7: 6, 8: 6, 10: 6, 14: 7, 15: 8, 18: 8, 20: 7, 27: 10, 29: 9, 40: 12, 57: 10, 61: 14, 91: 16, 104: 16, 133: 16, 194: 17, 233: 16, 308: 24, 425: 26, 530: 28, 735: 31, 1057: 33, 1308: 38, 1874: 32, 2576: 47, 3162: 45, 3769: 43, 3804: 55, 4872: 52, 6309: 63, 7731: 69, 11167: 69, 11476: 80, 15223: 90, 15603: 75, 16034: 82, 22761: 69, 29204: 110, 35268: 101, 42481: 105, 56238: 126, 68723: 113, 83062: 113, 95681: 160, 113965: 149, 152145: 148, 202644: 187, 287964: 238, 335302: 175, 376279: 258, 466202: 250, 475558: 247, 666030: 256, 743517: 237, 782403: 245, 903170: 278, 1078242: 256, 1435682: 408, 1856036: 304, 2373214: 401, 3283373: 286, 4545125: 328, 6215594: 510, 7309899: 616, 7848365: 458, 8096538: 683, 10409246: 754, 15103057: 787, 20271921: 653, 22186329: 957, 23602446: 754, 32341327: 1141, 33354300: 1033, 46852754: 984, 65157555: 839, 93637992: 1539, 107681394: 1130, 152487773: 1605, 181996529: 1845, 225801707: 1760, 324194358: 2346, 435824227: 2244, 579337939: 2670, 600264328: 2620, 827690923: 3047, 1129093889: 3334, 1260597310: 3813, 1473972478: 4076, 1952345052: 3946, 1977336057: 3599, 2512749509: 4414, 3278750235: 3600, 3747691805: 5580, 5146052509: 4751

Bagaimana itu bekerja:

1 butir telur:

Ketika ada satu telur, strategi terbaik adalah naik 1 lantai pada satu waktu dan mengembalikan lantai tepat di bawah lantai di mana ia pecah terlebih dahulu.

2 telur:

Ketika kita memiliki dua telur, jumlah lantai maksimum yang harus kita periksa akan menjadi n terkecil dimana T n lebih besar dari kisaran lantai yang harus kita periksa. T n adalah angka segitiga ke-n. Lemparan pertama akan dilakukan di lantai ke-n. Lemparan kedua akan dilakukan n - 1lantai di atas lemparan pertama. Lemparan ke-11 akan dilakukan di n - m + 1atas m - 1lemparan ke-10. Setelah telur pecah, dibutuhkan n - mlemparan untuk menentukan lantai dengan metode pertama.

3 telur:

Dengan telur pertama kita, kita harus menentukan batas atas untuk lantai tertinggi. Awalnya, saya melakukan ini dengan menggandakan nomor lantai setiap kali. Setelah menganalisis algoritma untuk 2 telur saya pikir mungkin akan lebih baik jika setiap kali kita melempar telur, max melempar untuk menemukan lantai yang benar dengan 2 telur akan meningkat 1. Ini dapat dipenuhi dengan menggunakan angka tetrahedral. Setelah telur pertama pecah, kita dapat menggunakan metode di atas untuk sisa telur kita.

Tetesan telur maks yang dibutuhkan untuk menentukan lantai harus optimal. Namun, algoritma yang lebih baik mungkin dapat ditemukan di mana rata-rata tetesan telur lebih baik.

TheNumberOne
sumber
4

Java, 68985 panggilan

public static long solve(Predicate<Long> eggSurvives) {
  long bestFloor = 0, e1 = 1, e2;

  for(long callsDone = 2; eggSurvives.test(e1); bestFloor = e1, e1 += callsDone * callsDone++);

  for(e2 = bestFloor;; bestFloor = e2) {
    e2 += Math.max((long)Math.sqrt(e1 - e2), 1);

    if(e2 >= e1 || !eggSurvives.test(e2)) {
      break;
    }
  }

  for(long e3 = bestFloor + 1; e3 < e2 && eggSurvives.test(e3); e3++) {
    bestFloor = e3;
  }

  return bestFloor;
}

Hasil tes:

0: 1 1: 4 2: 4 3: 4 4: 4 6: 6 7: 6 8: 6 10: 7 14: 6 15: 7 18: 7 20: 8 27: 10 29: 10 40: 10 57: 10 61: 9 91: 9 104: 11 133: 18 194: 20 233: 18 308: 18 425: 17 530: 17 735: 28 1057: 31 1308: 30 1874: 30 2576: 39 3162: 47 3769: 60 3804: 34 4872: 65 6309: 37 7731: 48 11167: 79 11476: 39 15223: 56 15603: 82 16034: 93 22761: 88 29204: 111 35268: 110 42481: 127 56238: 126 68723: 135 83062: 117 95681: 115 113965: 137 152145: 138 202644: 115 287964: 234 335302: 223 376279: 244 466202: 220 475558: 193 666030: 214 743517: 225 782403: 230 903170: 338 1078242: 223 1435682: 303 1856036: 384 2373214: 453 3283373: 542 4545125: 459 6215594: 525 7309899: 600 7848365: 388 8096538: 446 10409246: 466 15103057: 650 20271921: 822 22186329: 899 23602446: 698 32341327: 804 33354300: 1065 46852754: 1016 65157555: 1408 93637992: 1390 107681394: 1638 152487773: 1283 181996529: 1877 225801707: 2067 324194358: 1842 435824227: 3110 579337939: 2983 600264328: 1817 827690923: 2450 1129093889: 2981 1260597310: 3562 1473972478: 4237 1952345052: 2244 1977336057: 3585 2512749509: 2893 3278750235: 3101 3747691805: 5182 5146052509: 4107

Program uji:

import java.util.function.Predicate;

public class Eggs {
  private static long totalCalls;
  private static long calls;

  public static void main(String[] args) {
    for(long maxFloor : new long[] {0,1,2,3,4,6,7,8,10,14,15,18,20,27,29,40,57,61,91,104,133,194,233,308,425,530,735,1057,1308,1874,2576,3162,3769,3804,4872,6309,7731,11167,11476,15223,15603,16034,22761,29204,35268,42481,56238,68723,83062,95681,113965,152145,202644,287964,335302,376279,466202,475558,666030,743517,782403,903170,1078242,1435682,1856036,2373214,3283373,4545125,6215594,7309899,7848365,8096538,10409246,15103057,20271921,22186329,23602446,32341327,33354300,46852754,65157555,93637992,107681394,152487773,181996529,225801707,324194358,435824227,579337939,600264328,827690923,1129093889,1260597310,1473972478,1952345052,1977336057,2512749509L,3278750235L,3747691805L,5146052509L}) {
      long resultingFloor = solve(f -> {
        calls++;
        return f <= maxFloor;
      });

      if(resultingFloor != maxFloor) {
        throw new RuntimeException("Disqualified");
      }

      System.out.print(maxFloor + ": " + calls + " ");
      totalCalls += calls;
      calls = 0;
    }

    System.out.println("\nCalls = " + totalCalls);
  }

  public static long solve(Predicate<Long> eggSurvives) {
    long bestFloor = 0, e1 = 1, e2;

    for(long callsDone = 2; eggSurvives.test(e1); bestFloor = e1, e1 += callsDone * callsDone++);

    for(e2 = bestFloor;; bestFloor = e2) {
      e2 += Math.max((long)Math.sqrt(e1 - e2), 1);

      if(e2 >= e1 || !eggSurvives.test(e2)) {
        break;
      }
    }

    for(long e3 = bestFloor + 1; e3 < e2 && eggSurvives.test(e3); e3++) {
      bestFloor = e3;
    }

    return bestFloor;
  }
}

Sambil mengoptimalkan saya bertujuan untuk mencoba membuat jumlah upaya dengan masing-masing telur kira-kira sama.

  • Telur pertama naik dalam jumlah lantai berdasarkan jumlah upaya sejauh ini.
  • Telur kedua melompati lantai berdasarkan akar kuadrat dari jumlah upaya maksimum yang dapat dibiarkan (berdasarkan batas bawah dan atas yang ditetapkan oleh telur pertama) sehingga jumlah rata-rata upaya untuk telur ke-3 dan terakhir harus rata-rata sama dengan upaya untuk telur ke-2.
john16384
sumber
2

Ruby, 67466 66026 panggilan

$calls = 0

def drop n 
    $calls += 1
    n <= $x
end

def test
    min = 0
    test = 8
    i = 8
    while drop(test)
        min = test
        test += i*i
        i+=1
    end
    max = test
    test = min+((max-min)**0.4).to_i
    while drop(test)
        min = test
        test = min+((max-min)**0.5).to_i
    end
    return min if min+1 == test
    min += 1 while drop(min+1)
    min
end

Kode uji:

tests = [0,1,2,3,4,6,7,8,10,14,15,18,20,27,29,40,57,61,91,104,133,194,233,308,425,530,735,1057,1308,1874,2576,3162,3769,3804,4872,6309,7731,11167,11476,15223,15603,16034,22761,29204,35268,42481,56238,68723,83062,95681,113965,152145,202644,287964,335302,376279,466202,475558,666030,743517,782403,903170,1078242,1435682,1856036,2373214,3283373,4545125,6215594,7309899,7848365,8096538,10409246,15103057,20271921,22186329,23602446,32341327,33354300,46852754,65157555,93637992,107681394,152487773,181996529,225801707,324194358,435824227,579337939,600264328,827690923,1129093889,1260597310,1473972478,1952345052,1977336057,2512749509,3278750235,3747691805,5146052509]
tests.each{|n|$x = n;test;$calls}
puts $calls

Hasil:

0: 3, 1: 4, 2: 4, 3: 5, 4: 5, 6: 5, 7: 6, 8: 4, 10: 6, 14: 6, 15: 7, 18: 10, 20: 6, 27: 7, 29: 9, 40: 10, 57: 13, 61: 15, 91: 13, 104: 13, 133: 15, 194: 12, 233: 18, 308: 16, 425: 15, 530: 15, 735: 16, 1057: 32, 1308: 30, 1874: 35, 2576: 35, 3162: 54, 3769: 32, 3804: 29, 4872: 45, 6309: 42, 7731: 55, 11167: 72, 11476: 60, 15223: 55, 15603: 71, 16034: 94, 22761: 82, 29204: 119, 35268: 106, 42481: 123, 56238: 127, 68723: 110, 83062: 95, 95681: 139, 113965: 149, 152145: 149, 202644: 144, 287964: 219, 335302: 189, 376279: 183, 466202: 234, 475558: 174, 666030: 235, 743517: 195, 782403: 235, 903170: 346, 1078242: 215, 1435682: 245, 1856036: 422, 2373214: 448, 3283373: 512, 4545125: 378, 6215594: 502, 7309899: 486, 7848365: 440, 8096538: 496, 10409246: 566, 15103057: 667, 20271921: 949, 22186329: 829, 23602446: 746, 32341327: 799, 33354300: 964, 46852754: 1125, 65157555: 1317, 93637992: 1000, 107681394: 1361, 152487773: 1215, 181996529: 2004, 225801707: 1752, 324194358: 1868, 435824227: 3084, 579337939: 2592, 600264328: 1726, 827690923: 2577, 1129093889: 3022, 1260597310: 2582, 1473972478: 3748, 1952345052: 2035, 1977336057: 3712, 2512749509: 2859, 3278750235: 2888, 3747691805: 5309, 5146052509: 4234

Algoritma ini berfungsi seperti algoritma lama saya, tetapi memiliki beberapa perbedaan:

  1. Tetesan telur pertama ada di lantai 8

  2. Kenaikan pertama adalah 8 * 8 = 64

Angka-angka ini adalah hasil dari fine tuning acak dengan tangan.

MegaTom
sumber