Layar Kunci Android

25

Intro

Anda sedang duduk di ruang dewan di ujung meja panjang. Anda melihat-lihat dan melihat Tim Cook, Dewan Direksi Apple, hantu Steve Jobs, dan Jack Donaghy. Apple telah menyebut pertemuan ini karena mereka telah menyadari betapa kerennya layar kunci Android, dan mereka ingin 1-UP mereka. Semua orang di ruangan itu menatapmu ketika Ghost Steve berteriak, "Tolong aku, Manusia CodeGolf! Kau satu-satunya harapanku!"

Masalah

Layar kunci Android adalah kotak 3 x 3 titik yang dapat dihubungkan dengan menggesekkan jari dari satu titik ke titik berikutnya, menciptakan jalur. Kata sandi dianggap sebagai jalur yang memungkinkan yang mencakup sejumlah titik, dan tidak termasuk sejumlah titik. (Pada ponsel yang sebenarnya, panjang jalur harus minimal 4 titik. Untuk tantangan ini, abaikan pembatasan itu.) Apple berencana untuk mengganti kisi 3 x 3 dengan kisi M x N, yaitu (M * N) / 9 kali lebih baik!

Aturan:

  • Jalur nol titik bukanlah kata sandi, tetapi jalur 1 titik
  • Sebuah jalan dapat melintasi dirinya sendiri
  • Jalur tidak dapat melintasi langsung titik tanpa termasuk titik itu
  • Satu titik hanya bisa digunakan satu kali
  • Jalur yang identik dengan rotasi bukanlah kata sandi yang sama
  • Jalur yang identik tetapi dipesan secara terbalik bukanlah kata sandi yang sama
  • Misalnya, pada kisi 3x3 dengan titik-titik bernomor mulai 1 hingga 9:

    1 2 3
    4 5 6
    7 8 9
    

    Beberapa jalur yang valid adalah:

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

    Dan beberapa jalur yang tidak valid adalah:

    1,3
    1,9,5
    7,5,4,7
    4,6
    

    Input Anda akan terdiri dari tiga angka:

    (M,N,d)
    

    Di mana kisi-kisi adalah M x N, dan d adalah panjang jalur

    1 <= M <= 16
    1 <= N <= 16
    1 <= d <= M * N
    

    Program atau fungsi Anda akan diberi input sebagai string yang dipisah koma, dan itu harus mengembalikan jumlah kata sandi yang mungkin panjangnya. Sebagai contoh:

    Input:  2,2,1 
    Output: 4
    Input:  2,2,2
    Output: 12
    Input:  7,4,1
    Output: 28
    

    Aturan golf kode standar berlaku, kode terpendek menang!

    //If I've made a mistake or the rules are unclear, please correct me!
    
    Platatat
    sumber
    2
    Apakah input berupa string yang dipisahkan koma atau tiga parameter terpisah?
    user80551
    1
    @ user80551 Berdasarkan konteksnya, saya pikir itu akan menjadi string jika itu adalah input ke suatu program, atau parameter yang terpisah jika digunakan untuk memanggil fungsi.
    user12205
    1
    @Platatat dapatkah Anda menjawab pertanyaan user80551, karena ini benar-benar penting untuk merancang kode
    RononDex
    3
    Anda harus memutuskan apakah akan ada batas waktu untuk waktu kompilasi dan eksekusi dari solusi yang diberikan. Tanpa batas seperti itu, mudah untuk menulis sebuah program yang, dalam teori, memverifikasi mana dari semua 256!permutasi dari titik-titik pada kisi 16 x 16 yang mewakili pola buka kunci yang valid. Dalam praktiknya, program semacam itu tidak akan pernah berakhir.
    Dennis
    3
    Tapi saya bilang masalahnya didasarkan pada sistem kunci android ... Jadi mengapa saya tidak menggunakan aturan yang sama dengan sistem kunci android?
    Platatat

    Jawaban:

    14

    Python - 170 byte

    from fractions import*
    p=lambda m,n,d,l=0,s=set():d<1or sum([p(m,n,d-1,i,s|{i})for i in range(m*n)if not(s and(s&{i}or set(range(l,i,abs(i-l)/gcd(i%n-l%n,i/n-l/n)))-s))])
    

    Saya menyadari bahwa tanda kurung di dalam sum([...])tidak sepenuhnya diperlukan, tetapi ada penalti kinerja yang besar untuk tidak memasukkannya.

    Output untuk semua 3x3:

    for i in range(4, 10):
      print p(3, 3, i)
    

    Menghasilkan:

    1624
    7152
    26016
    72912
    140704
    140704
    

    Untuk tujuan pengujian / konfirmasi, 6 nilai pertama untuk papan 4x5:

    20
    262
    3280
    39644
    459764
    5101232
    

    4x5 adalah kasus yang menarik untuk diverifikasi, karena memiliki lompatan pasak 2x2, 3x3, dan 2x4.


    Penjelasan singkat

    Secara umum, ini adalah pencarian lengkap, dengan pemangkasan kumulatif. Misalnya, karena p(3, 3, 4)1624, p(3, 3, 5)hanya akan memeriksa 8120 kemungkinan, daripada memeriksa semua 15120 secara naif. Sebagian besar logika terkandung dalam kondisi:

    if not(s and(s&{i}or set(range(l,i,abs(i-l)/gcd(i%n-l%n,i/n-l/n)))-s))
    

    Dalam bahasa Inggris yang sederhana, ini dapat dipahami sebagai:

    If no pegs have been used yet
         OR
       the target peg has not yet been used
         AND
       each of the pegs directly between the target peg and the
       current peg (a.k.a. "jumped over") have already been used
    
    primo
    sumber
    2
    Bisakah Anda menjelaskan apa yang sedang terjadi di sini?
    ɐɔıʇǝɥʇuʎs
    1
    Anda dapat menyimpan beberapa byte dengan smenetapkan satu set alih-alih daftar. Saya tidak melihat penalti kinerja besar menjatuhkan kurung; mengapa akan ada hukuman seperti itu?
    user2357112 mendukung Monica
    1
    @ user2357112 satu menjumlahkan Generator, yang lain atas Daftar. Dengan CPython, Anda benar, tidak ada banyak perbedaan (hanya sekitar 20% lebih lambat). Dengan PyPy, ini lebih dari 5 kali lebih lambat.
    Primo
    1
    @ user2357112 Saya akhirnya melihat apa yang Anda maksud dengan mendefinisikan ssebagai set. Pelajaran python saya untuk hari ini: {i}dievaluasi sebagai set([i]). Saya akan mengharapkan kesalahan sintaksis. Menambahkan item ke set kemudian menjadi s|{i}, dan juga memungkinkan i in suntuk digantikan oleh s&{i}.
    Primo