R ve n verildiğinde, x'in ilk basamağını sona taşımak x / r = y değerini veren x'in ilk n sayısını bulun


11

Amaç

Girilen rve nilk ndoğal sayıları bulmak böylece xilk basamağı elde son konuma döner x/r.

Bunu varsayabilirsin 2 <= r <= 9ve 1 <= n <= 65535.

Stdin veya komut satırı argümanlarından girdi alan bir program yazabilirsiniz; veya parametre olarak rve nparametre olarak bir işlev yazabilirsiniz . Ancak çıktı stdout olmalıdır. Çıktı , artan sırayla x, her değer için bir satır olmalıdır .x/r=yx

Çözümünüz makul bir masaüstü bilgisayarda tüm geçerli durumları bir dakika içinde ele alabilmelidir.

Test senaryoları

Giriş: 4 5
Çıkış:

102564/4=25641  
205128/4=51282  
307692/4=76923  
410256/4=102564  
512820/4=128205

Giriş: 5 1
Çıkış:714285/5=142857

Bu kod golf, yani en az bayt kazanır. Kazanan cevap bundan 4 hafta sonra kabul edilecektir (2014-09-19).

Bu soru için verilen krediler, bu soruyu buraya göndermeme izin veren meslektaşımın yanına gitti :)


Zaman kısıtlaması, gereken çıktı miktarı ile zordur. Buna göre gprof, programım için bir giriş durumu kodumda yarım saniyeden daha az harcıyor, ancak toplamda yaklaşık 80 saniye sürüyor, ki bu da çoğunlukla çıktıda engelleme olması gerektiğini varsayıyor.
aschepler

Ah, kaçınarak etrafta dolaştım printf.
aschepler

Yanıtlar:


7

Haskell, 182 179

İkinci versiyon, muhtemelen daha fazla golf yapılabilir, ancak bu sefer "uygun" algoritma ile. Özellikle, r=4ve ile birkaç dakika içinde biter n=65535, ancak daha sonra bilgisayarım ne makul ne de bir masaüstü, bu yüzden bu diğer makinelerde bir dakika içinde kalır.

n#r=take n$[s(10^k*a+d)++'/':s r++'=':s d++s a|k<-[0..],a<-[1..9],let(d,m)=divMod(a*(10^k-r))(10*r-1),m<1]
s=show
main=interact$unlines.(\(r:n:_)->n#fromIntegral r).map read.words

x=10^k*a + mİlk hanesinin 0≤a≤9elde etmek için sonuna taşındığı fikrine dayanır y=10*m+a. Biraz matematik ortaya koymaktadır molarak elde edilebilir a*(10^k-r)/(10*r-1)biz sadece tarama böylece, aüzerinde [1..9]her için ksonsuza 0'dan ve tutmak ve ilk baskı niçin yukarıda ifade hangi sonuçları mayrılmaz bir parçasıdır.

fromIntegralGereklidir, çünkü readbir liste ing nyılında unsurlardan biri olarak main, kullanımı ile kombinasyon halinde nde take, zorlayacaktır riçin Intsöz konusu büyük sayılarla pis taşmalarıyla hangi sonuçları boyunca. Kullanabilirdim genericTake, ama bu bir gerektirir import.

Bu kod ayrıca 10'dan farklı bazlara genişlemek için neredeyse önemsiz olma avantajına sahiptir.

Giriş okunur stdin, iki değer herhangi bir boşlukla ayrılabilir.


Eğer backsticks kurtulmak kodunuzu daha kısa olmalıdır
gurur haskeller

@proudhaskeller: emin değilim çünkü etrafında boşluk bırakmadan operatörü ve operandı ayıracak parantez yok.
TheSpanishInquisition

Haskell'i okuyamıyorum, bu yüzden ne yaptığınızdan tam olarak emin değilim. Bu r = 5; n = 65535bir dakika içinde çözülecek mi?
Martin Ender

@ MartinBüttner: Bu yorumu bekliyordum. Evet, muhtemelen öyle, ama bilgisayarımda değil (veya şu anda başka biri değil). Sorunun daha gelişmiş bir algoritmaya ihtiyacı olduğunu düşünüyorum. :(
TheSpanishInquisition

@TheSpanishInquisition Ancak yerine daha kısa bir süre y`mod`10ile değiştirebilirsinizmod y10
gurur haskeller

1

Saf Bash (harici yardımcı program yok), 80 bayt

for((;++x,c<$2;));{
y=$[10#${x:1}${x:0:1}]
((y*$1==x))&&echo $x/$1=$y&&((c++))
}

Bash sadece tamsayı aritmetik ve kayan nokta değil, bu yüzden x == y * ryerine kontrol edin x / r == y. Ayrıca çarpma işlemi genellikle daha hızlı olmalıdır. Yine de bu, performans gereksinimini karşılayacak bir yere yakın değil.

Çıktı:

$ ./rotdiv.sh 4 5
102564/4=25641
205128/4=51282
307692/4=76923
410256/4=102564
512820/4=128205
$ ./rotdiv.sh 5 1
714285/5=142857
$ 

1

C 468

#include <stdlib.h>
#include <stdio.h>
#define a(s)fputs(s,stdout);
#define b(c)putchar(c);
int r;int z(char*s,int m){for(int i=0;i++<=m;)a(s)b(47)b(r+48)b(61)char*t=s;
while(*++t==48);a(t)while(m--)a(s)b(*s)b(10)}char x[10][60];
int main(int c,char**v){r=atoi(v[1]);int n=atoi(v[2]),q=10*r-1,d=0,p;
while(d++<9){p=r*d;char*y=x[d];do{p*=10;*y++=p/q+48;p%=q;}while(p!=r*d);}
d=1;p=q=0;while(n--){r==5&p<6?z(x[7],7*q+p++):(z(x[d],(r==5&d==7)?7*q+6:q),
++d>9?q+=d=1,p=0:0);}}

(Bayt sayımında sayılmayan bazı yeni satırlar, kaydırma çubuklarını ortadan kaldırmak için yukarıda eklenmiştir. Evet, son yeni satır sayılır.)

Komut satırındaki bağımsız değişkenleri bekler ve standart çıktının ASCII'yi kabul ettiğini varsayar. Çalışma zamanı O (bayt çıkış sayısı) = O (n * n).

Hayır, kullanamam printf. Bu çok fazla zaman alıyor ve programı masaüstümdeki dakika sınırını zorluyor. Olduğu gibi, bazı test vakaları yaklaşık 30 saniye sürer.

Algoritma, çıktıyı sayı olarak değil, sayı olarak ele alır, çünkü hızla büyürler ve çıktıda güçlü desenler vardır.

Biraz soluksuz:

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

/* r is as in the problem description */
int r;

void show_line(const char* num, int repeats) {
    for (int i=0; i <= repeats; ++i)
        fputs(num, stdout);
    printf("/%c=", '0'+r);

    /* Assume the repeated num is a solution. Just move the first
       digit and skip any resulting leading zeros. */
    const char* num_tail = num;
    ++num_tail;
    while (*num_tail=='0')
        ++num_tail;
    fputs(num_tail, stdout);
    while (repeats--)
        fputs(num, stdout);
    printf("%c\n", *num);
}

/* sol[0] is unused. Otherwise, sol[d] is the repeating digits in the
   decimal representation of (r*d)/(10*r-1). */
char sol[10][60];

int main(int argc, char** argv) {
    r = atoi(argv[1]);
    int n = atoi(argv[2]);
    int q = 10*r-1;
    int d = 0;

    /* Populate the strings in sol[]. */
    while (d++<9) {
        int p = r*d;
        char* sol_str = sol[d];

        /* Do the long division p/q in decimal, stopping when the remainder
           is the original dividend. The integer part is always zero. */
        do {
            p *= 10;
            *sol_str++ = p/q + '0';
            p %= q;
        } while (p != r*d);
    }

    /* Output the answers. */
    d = 1;
    int repeats = 0;
    int r5x7_repeats = 0;
    while (n--) {
        if (r==5 && r5x7_repeats<6) {
            show_line(x[7], 7*repeats + r5x7_repeats);
        } else {
            if (r==5 && d==7)
                show_line(x[d], 7*repeats + 6);
            else
                show_line(x[d], repeats);
            if (++d > 9) {
                d = 1;
                ++repeats;
                r5x7_repeats = 0;
            }
        }
    }
}

Kanıt

programın sorunu çözdüğünü:

(İspatta, tüm operatörleri ve işlevleri gerçek matematiksel işlevler olarak kabul edin, onlara yaklaşan bilgisayar işlemleri ^değil. Bit ile xor değil, üstellemeyi belirtir.)

Anlaşılır olması için, ToDecbir sayıyı ondalık basamak dizisi olarak sıradan yazma işlemini tanımlamak için bir işlev kullanacağım . Aralığı, sipariş edilen tuples setidir {0...9}. Örneğin,

ToDec(2014) = (2, 0, 1, 4).

Pozitif bir tamsayı için n, L(n)ondalık gösterimindeki basamak sayısı olarak tanımlayın n; veya,

L(n) = 1+floor(log10(n)).

Pozitif bir tamsayı kve nile negatif olmayan bir tamsayı için , eğer ondalık basamakların önüne sıfır ekleyerek , eğer toplam rakamları elde etmek için gerekirse sıfırlar ekleyerek elde edilen gerçek sayı olarak L(n)<ktanımlayın ve daha sonra ondalık noktadan sonra bu basamakları sonsuz bir şekilde tekrarlayın . ÖrneğinRep_k(n)nkk

Rep_4(2014) = .201420142014...
Rep_5(2014) = .020140201402...

Çarpma , ondalık noktadan Rep_k(n) * 10^könceki basamaklarını nve ondalık noktadan nsonra sonsuz tekrarlanan (sıfır dolgulu) basamakları verir . Yani

Rep_k(n) * 10^k = n + Rep_k(n)
Rep_k(n) = n / (10^k - 1)

Olumlu bir tam sayı verildiğinde r, varsayalım x, soruna bir çözümdür ve

ToDec(x) = ( x_1, x_2, ..., x_k )

nerede x_1 != 0ve k = L(x).

Bir çözüm olarak, xbir katıdır rve

ToDec(x/r) : ( x_2, x_3, ..., x_k, x_1 ).

Rep_kFonksiyonu uygulamak hoş bir denklem verir:

10*Rep_k(x) = x_1 + Rep_k(x/r)

Yukarıdan kapalı formunu kullanarak,

10x / (10^k - 1) = x_1 + x / r / (10^k - 1)
x = x_1 * r * (10^k-1) / (10r - 1)

x_1sette olmalıdır {1 ... 9}. rsette olduğu belirtildi {2 ... 9}. Şimdi tek soru, kyukarıdaki formülün hangi değerleri için xpozitif bir tamsayı veriyor? Her olası değeri rayrı ayrı ele alacağız .

Zaman r= 2, 3, 6, 8 ya da 9, 10r-1sırası ile, 19, 29, 59, 79, ya da 89 olduğu. Her durumda payda p = 10r-1asaldır. Payda, sadece 10^k-1katları olabilir p,

10^k = 1 (mod p)

Çözelti kümesi, negatif sayı ile sonuçlanmayan toplama ve çıkarma altında kapatılır. Bu yüzden küme, aynı zamanda en az pozitif çözüm olan bazı ortak faktörlerin tüm katlarını içerir k.

Ne zaman r = 4ve 10r-1 = 39; veya r = 7ve 10r-1 = 69payda 3 kez farklı bir asal p=(10r-1)/3. 10^k-1her zaman 3'ün katlarıdır ve yine paydaki başka hiçbir faktör katları olamaz p, bu yüzden sorun yine

10^k = 1 (mod p)

ve yine çözeltiler, en az pozitif çözeltinin katlarıdır k.

[Bitmedi...]


0

Python - 91 90

İşte ilk çekim:

r,n=input();i=1
while n:
 if int(`i`[1:]+`i`[0])*r==i:print'%d/%d=%d'%(i,r,i/r);n-=1
 i+=1

Düzenleme: Tamam, muhtemelen 65K numaraları için gerekli 1 dakikalık zaman sınırını karşılamak için yavaş yolu.


1
Bunu performans gereksinimine göre test ettiniz mi?
Peter Taylor

2
Güneş patlamadan önce bunun 65 bin kişi bulacağına dair şüphelerim var.
Martin Ender

0

JavaScript - 145

function f(a,b){for(d=0;d<b;d++)for(i=1;;i++){c=i/a;if(c==parseInt(i.toString().substring(1)+i.toString().charAt(0)))console.log(i+'/'+a+'='+c)}}

golf oynamayan:

function f(a,b){
    for(d=0;d<b;d++) //loop for the right amount
        for(i=1;;i++){ //iterating loop
            c=i/a; //actual result of the division
            if(c==parseInt(i.toString().substring(1)+i.toString().charAt(0)))
                console.log(i+'/'+a+'='+c)
        }
}

Bunu hiç çalıştıramadım, ama olsa bile, performans gereksinimini karşılayacağından şüpheliyim.
Martin Ender

@ MartinBüttner benim için mükemmel çalışıyor. performans gereksinimlerini karşılamıyor olabilir ama şu anda ben bilgisayar oldukça zayıf ... Bu kod parçasının çalışması için ne yaptınız?
Armin

1
Konsola kopyaladı ve ekledi (5,4). Çalışmamasının nedeni sayıların çok artmasıdır. a) JS'deki bir sayıdan çok daha büyük olanı doğru bir şekilde temsil edebilir ve b) oraya ulaşmak için tüm sayılar arasında yineleme yapılabileceği için çok büyük.
Martin Ender

0

Python 3 - 223 179 bayt

TheSpanishInquisition'ın çözümünün Python uygulaması:

r,n=map(int,input().split());k=0
while 1:
 for a in range(1,10):
  D,M=divmod(a*(10**k-r),10*r-1)
  if M==0:
   print("%d/%d=%d"%(a*10**k+D,r,10*D+a));n-=1
   if n==0:exit()
 k+=1

Çalıştırmak:

  • python3 <whatever you named it>.py
  • Stdin hakkında girdi alır
  • Giriş alanı ayrıldı

Çıktı:

$python3 <whatever you named it>.py
4 8
102564/4=25641
205128/4=51282
307692/4=76923
410256/4=102564
512820/4=128205
615384/4=153846
717948/4=179487
820512/4=205128

Bulgular:

Her r için ilk değer https://oeis.org/A092697'dir .

Öyle görünüyor ki sadece belirli k değerleri cevap veriyor ve aralığın düzenli olduğu görülüyor. Örneğin r = 4 için:

Form: k [a, a, ...]
0 []
1 []
2 []
3 []
4 []
5 [1, 2, 3, 4, 5, 6, 7, 8, 9]
6 []
7 []
8 []
9 []
10 []
11 [1, 2, 3, 4, 5, 6, 7, 8, 9]
12 []
13 []
14 []
15 []
16 []
17 [1, 2, 3, 4, 5, 6, 7, 8, 9]
18 []
19 []
20 []
21 []
22 []
23 [1, 2, 3, 4, 5, 6, 7, 8, 9]

Aralıklar:

  • 2 = 18
  • 3 = 28
  • 4 = 6
  • 5 = 6 (5 bir anomali gibi görünüyor, r'nin çoğu değeri için, 9'dan oluşan kümeler, 9 ve 1'den oluşan 5 kümeler var (sadece a = 7 çalışıyor), aşağıya bakın)
  • 6 = 58
  • 7 = 22
  • 8 = 13
  • 9 = 44

Bu, https://oeis.org/A094224 biçimini oluşturur .

Bu değerleri kullanarak daha verimli bir sürüm oluşturulabilir:

import math

def A094224(n):
    return [18,28,6,6,58,22,13,44][n-2]


r,n=map(int,input().split());k=A094224(r)-1
H={}
while 1:
    for a in range(1,10):
        D,M=divmod(a*10**k-a*r,10*r-1)
        if M==0:
            print("%d/%d=%d"%(a*10**k+D,r,10*D+a));n-=1
            if n==0:exit()
    k+=A094224(r)

Ancak, bunun matematiksel olarak devam ettiğini (henüz) kanıtlayamıyorum.

R = 5 için sonuçlar:

0 []
1 []
2 []
3 []
4 []
5 [7]
6 []
7 []
8 []
9 []
10 []
11 [7]
12 []
13 []
14 []
15 []
16 []
17 [7]
18 []
19 []
20 []
21 []
22 []
23 [7]
24 []
25 []
26 []
27 []
28 []
29 [7]
30 []
31 []
32 []
33 []
34 []
35 [7]
36 []
37 []
38 []
39 []
40 []
41 [1, 2, 3, 4, 5, 6, 7, 8, 9]

2
Girdi ile test ettiniz 9 65535mi?
Peter Taylor

Muhtemelen unsigned long longbunun için kullanmalıyım ve bunu bir dakika içinde yapmak için çok çekirdekli yapmalıyım.
matsjoyce

1
Eğer unsigned long long64 bit, bu yeterince büyük değil.
Peter Taylor

Doğru, @ TheSpanishInquisition'ın çözümüne geçtim ve bunun yerine python kullandım.
matsjoyce
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.