Mencari alternatif yang lebih pendek untuk `range (...)`

8

Solusi terbaik yang saya temukan sejauh ini untuk teka-teki kode golf yang saya kerjakan termasuk dua doa yang agak gemukrange . Saya sangat baru di golf kode, terutama di Python, jadi saya bisa menggunakan beberapa tips.

Fragmen yang relevan adalah ini

[x for x in range(n+1,7**6)if`x`==`x`[::-1]*all(x%i for i in range(2,x))]

Batas atas yang pertama rangebukan yang tajam. Seharusnya setidaknya 98690, dan semua yang lain sama (berdasarkan golf), semakin kecil perbedaan antara batas atas ini dan 98690 semakin baik, berdasarkan kinerja 1 . Saya menggunakan 7 6 (= 117649) karena 7**6merupakan ekspresi Python terpendek yang dapat saya buat yang sesuai dengan tagihan.

Sebaliknya, batas bawah di yang pertama range, serta kedua batas di yang kedua, tegas. TKI, program (dalam bentuk saat ini) akan menghasilkan hasil yang salah jika batas tersebut diubah.

Apakah ada cara untuk mempersingkat satu atau kedua ekspresi

range(n+1,7**6)
range(2,x)

?

BTW, dalam hal ini, alias range, katakanlah, rtidak memperoleh apa-apa:

r=range;rr
rangerange

EDIT: FWIW, program lengkapnya adalah ini:

p=lambda n:[x for x in range(n+1,7**6)if`x`==`x`[::-1]*all(x%i for i in range(2,x))][0]

p(n)harus menjadi prime palindromic terkecil yang lebih besar dari n. Juga, pjangan rekursif. Peringatan: Ini sudah sangat lambat!


1 Ya, saya tahu: kinerja tidak relevan dalam kode golf, tapi itu sebabnya saya menulis "semuanya sama (golf-wise, that is)". Sebagai contoh, pilihan saya 7**6, dan bukan alternatif yang "jelas-setara" yang lebih jelas, tetapi berkinerja buruk 9**9. Saya suka benar - benar menjalankan upaya kode golf saya, yang berarti tidak membiarkan kinerja menurun ke titik yang membutuhkan waktu bertahun-tahun untuk menjalankan kode. Jika saya dapat membantu, tentu saja.

kjo
sumber
1
fwiw, Anda bisa membuat milik Anda jauh lebih cepat untuk keperluan pengujian dengan menggunakan generator; itu setara kecuali bahwa: p=lambda n:(x for x in xrange(n+1,7**6)if`x`==`x`[::-1]*all(x%i for i in xrange(2,x))).next(). Tentu saja, sementara Anda pada saat itu, mungkin juga berubah xrange(2,x)untuk xrange(2,int(x**.5+1))dan membuat pengujian Anda benar-benar cepat. Jelas kode ini setara dengan kode Anda, lebih lama dan lebih cepat.
Justin
1
Tidak mungkin menghasilkan banyak trik golf yang bagus dengan fragmen pendek yang terisolasi dari konteksnya. Program golf terbaik sering membuat koneksi yang mengejutkan antara berbagai bagian program. Misalnya, variabel yang tampaknya tidak berguna yang dibuang dapat membuktikan kunci, atau dua loop yang tidak terkait digabungkan menjadi satu.
feersum
@feersum: Saya memposting semuanya (dalam EDIT) beberapa waktu yang lalu. Itu sebelum Anda memposting komentar Anda. Apakah kamu tidak melihatnya?
kjo
@FryAmTheEggman: ya, pernyataan dari teka-teki adalah bahwa itu harus menjadi fungsi, dan, yang lebih buruk, fungsi tidak dapat menjadi rekursif.
kjo
1
Anda mungkin ingin melihat di sini
Beta Decay

Jawaban:

7

Buat satu loop

Seperti, Anda memiliki dua loop: satu iterasi di atas xyang mungkin merupakan bilangan prima palindromik, yang lain iterasi iuntuk memeriksa apakah xprima dengan divisi percobaan. Seperti yang Anda perhatikan, loop adalah Python mengambil banyak karakter, seringkali untuk menulis range, tetapi juga untuk menulis while _:atau for x in _. Jadi, solusi Python golf harus bersusah payah menggunakan loop sesedikit mungkin.

komentar feersum "Program golf terbaik sering membuat koneksi mengejutkan antara bagian yang berbeda dari program" sangat berlaku di sini. Pemeriksaan prima mungkin tampak seperti subrutin terpisah yang all(x%i for i in range(2,x))merupakan ekspresi klasik. Tapi kita akan melakukannya dengan cara lain.

Idenya adalah menggunakan Teorema Wilson . Untuk setiap prime potensial k, kami menyimpan produk yang sedang berjalan (k-1)!, dan memeriksa apakah ini merupakan kelipatan k. Kita bisa melacaknya(k-1)! sementara kita menguji potensi kuntuk menjadi palindrom utama dengan menjaga produk yang berjalan P.

Sebenarnya, kita akan menggunakan versi yang lebih kuat dari Teorema Wilson yang (k-1)! % ksama dengan 0 untuk komposit kdan hanya untuk angka komposit, kecuali k=4memberi 2, dan (k-1)!**2 % ksama dengan 0persis untuk angka komposit. Kami akan memperbaruiP ke sama k!**2melalui pembaruan P*=k*k.

(Lihat jawaban ini untuk metode ini yang digunakan untuk menemukan bilangan prima dengan Python.)

Menyatukan semuanya:

def p(n):
 k=P=1
 while(`k`!=`k`[::-1])+(k<=n)+(P%k==0):P*=k*k;k+=1
 return k

Ini belum sepenuhnya golf - kondisi khususnya ditulis tidak efisien. Kita dapat mengompres kondisi untuk memeriksa itu kadalah palindrom sementara pada saat itu menegakkan kondisi lain melalui ketimpangan dirantai.

def p(n):
 k=P=1
 while`k`*(P%k>0>n-k)!=`k`[::-1]:P*=k*k;k+=1
 return k
Tidak
sumber
1
solusi yang mempesona. Saya bersyukur melihatnya, meskipun masuk ke ranah di luar jangkauan saya ... Sampai sekarang peningkatan saya dalam golf semuanya adalah masalah mengambil trik seperti menggunakan backticks, bukan str, tetapi trik ini mendapatkan hanya satu sehingga banyak ... perbaikan besar datang dari algoritma yang lebih baik, seperti biasa.
kjo
1
Mengikuti solusi FryAmTheEggman, seseorang dapat menulis ulang kondisinya sebagai `k`*(k>n)*(P%k>0)!=`k`[::-1], yang mencukur 4
kjo
1
@ kjo Ya, dan bahkan lebih mirip lagi jika Anda rantai ketidaksetaraan menjadi satu. Anda juga harus melihat Latihan Golf Python juga melihat trik seperti ini
xnor
itu dilakukan dengan sangat baik! Terima kasih semua! ini telah menjadi utas yang sangat membuka mata saya ... solusi terpendek yang saya ketahui, untuk Python 2.7 dan 3.3, masing-masing, 28 dan 32 karakter lebih pendek dari versi yang saya posting pada awalnya (upaya terbaik saya), dan ketika saya menemukan ini saya tidak percaya; Saya pikir harus ada beberapa permainan busuk di suatu tempat (misalnya dengan merekayasa balik program pengujian-solusi otomatis). tetapi setelah melihat bagaimana para ahli di sini dengan cepat mencukur hingga 16 karakter dari upaya terbaik saya, saya sekarang lebih bersedia untuk mempercayai angka-angka itu.
kjo
@ kjo Saya senang Anda melihat keajaiban keajaiban golf. Apakah Anda mengatakan ada solusi 55 char? Jika demikian, saya tertarik. Apakah ini masalah golf anarki? Bisakah Anda menautkan saya ke pernyataan masalah? Mungkin ada jalan pintas yang mungkin dari celah dalam kasus uji, khususnya pengecualian dengan angka 4.
xnor
3

AFAIK, tidak juga.

Rentang umumnya digunakan dalam golf python karena merupakan cara terpendek untuk menghasilkan daftar angka yang bertambah / berkurang.

Yang mengatakan, itu tampaknya sedikit (7 byte) lebih pendek untuk menghindari menggunakan jangkauan dan alih-alih memanggil loop sementara:

def p(n):
    n+=1
    while`n`*all(n%i for i in range(2,n))!=`n`[::-1]:n+=1
    return n

Terima kasih kepada @xnor (seperti biasa) untuk meningkatkan logika kondisi sementara :)

FryAmTheEggman
sumber
@ kjo Tidak ada masalah :) Anda mungkin ingin menambahkan apa yang Anda katakan kepada saya tentang itu harus menjadi fungsi non-rekursif untuk pertanyaan, karena jika tidak, jawaban ini agak buruk;)
FryAmTheEggman
2
Anda dapat menghemat kondisi tersebut dengan secara implisit meniadakan itu: while(`n`!=`n`[::-1])+0in(n%i for i in range(2,n)):n+=1. Saya sepertinya tidak bisa menghilangkan pasangan pertama karena masalah prioritas operator.
xnor
2
Menyingkirkan orangtua:while`n`*all(n%i for i in range(2,n))!=`n`[::-1]:n+=1
xnor
@FryAmTheEggman: Anda sangat sportif! selesai
kjo
1

Saat menggunakan algoritma iteratif seperti metode Newton atau menghitung fraktal, di mana Anda biasanya perlu melakukan iterasi tanpa benar-benar peduli dengan indeks Anda dapat menyimpan beberapa karakter dengan mengulangi string pendek sebagai gantinya.

for i in range(4):x=f(x)
for i in'asdf':x=f(x)

Pada tujuh iterasi ini impas dengan range. Untuk iterasi yang lebih banyak gunakan backtics dan angka besar

for i in`9**9**5`:pass

Ini berjalan 56.349 kali yang seharusnya cukup untuk semua tujuan praktis. Bermain-main dengan angka dan operator memungkinkan Anda melakukan hardcode berbagai nomor dengan cara ini.

DenDenDo
sumber
Meskipun ini menarik, Anda dapat melihat dengan jelas bahwa dia peduli dengan indeks (karena kandidat utama adalah indeks). Saya pikir ini lebih cocok sebagai bagian dari jawaban ini pada halaman tips sebagai gantinya :) (Perhatikan juga bahwa '1'*4lebih pendek dari 'asdf')
FryAmTheEggman