Digital River (En Kısa Ve En Hızlı Çözüm)


9

Bu benim ilk sorum, umarım iyi gidiyor.

Arka fon:

Düşündüğünüz nehirler değil. Soru, dijital nehir kavramı etrafında dönüyor. Dijital bir nehir sayısı aşağıdaki bir sayı dizisi nolup nartı basamak toplamıdır.

Açıklama:

12345 12360 1 beri + 2 + 3 + 4 + 5 = 15 izledi ve böylece 12345 + 15 dijital nehrin ilk sayı ise 12360. Benzer 145 155 ile izlemektedir verir Mbiz nehir var arayacak M.

Örneğin: 480 nolu nehir {480,492,507,519 ....} ile başlayan dizidir ve 483 nolu nehir (483,498,519, ....} ile başlayan dizidir. Normal akışlar ve nehirler buluşabilir ve aynı şey dijital nehirler için de geçerlidir. Bu, iki dijital nehir aynı değerlerden bazılarını paylaştığında olur.

Misal:

480 nehri 519'da 483 nehri ile buluşur. 480 nehri 507'de 507 nehri ile hiçbir zaman 481 nehri ile buluşmaz. Her dijital nehir nihayetinde 1 nehri, 3 nehri veya 9 nehri ile buluşur.

Belirli bir tamsayı niçin nehrin nbu üç nehirden biriyle buluştuğu değeri belirleyebilecek bir program yazın .

Giriş

Giriş, birden fazla test durumu içerebilir. Her test durumu ayrı bir satır kaplar ve bir tamsayı n( 1 <= n <= 16384) içerir . Değerine sahip bir test durumu 0için ngiriş sona erer ve bu test durumda işleme edilmemelidir.

Çıktı

Girişteki her test durumu için ilk önce örnek çıkışında gösterildiği gibi test durumu numarası (1'den başlayarak). Sonra ayrı bir satırda "ilk önce y'de x nehri ile buluşur" satırı çıkar. Burada y, nehrin nilk önce nehirle buluştuğu en düşük değerdir x(x = 1 veya 3 veya 9). nNehir x, ybirden fazla değerinde nehri karşılarsa x, en düşük değeri çıktılayın. Art arda iki test durumu arasında boş bir satır yazdırın.

Test durumu

Giriş:

86
12345
0

Çıktı:

Case #1

first meets river 1 at 101

Case #2

first meets river 3 at 12423

puanlama:

En hızlı algoritma kazanır. Beraberlik durumunda. Kısa kodlu olan kazanır.

Benim hata işaret için mbomb007 teşekkürler .

ps: En küçük çözüm yerine en hızlı çözüme sahip olmak istiyorum. Benim de yavaş olan bir çözümüm var. Bunun için buraya bak .

Not:

Ben kullanıyor olacaktır bu kod test için. Ve performans kontrolü.


3
Bu şekilde gol atabileceğinden emin değilim. Birinin kodu O (log (log n)) ise ne olur? Hepsini kapsayamazsınız, bu yüzden en hızlı algoritmanın kazandığını söylemelisiniz, ancak bir kravat durumunda, en kısa kod kazanır ve her ikisinin de aynı uzunlukta olması durumunda ilk yayınlanan kazanır.
mbomb007

3
Eski ACM-ICPC zorluklarının telif hakkı veya kullanılabilirliği hakkında hiçbir şey bulamıyorum, ancak bu zorluğu arşiv sitesinde bulabilirim. Burada kullanılmasına izin veriliyor mu?
Geobits

1
Bunun telif hakkı ile ilgisi yok. Şüpheniz varsa, en kolay şey normal olarak site sahiplerine e-posta göndermek ve sormaktır.
Geobits

3
" Eğer dijital bir nehrin son basamağı Mona nehir diyeceğizM " iki nedenden dolayı mantıklı gelmez: Birincisi, eğer bir nehir sonsuz bir sayı dizisiyse, o zaman bir son basamağı yoktur; ve ikincisi, bir sonraki paragrafta nehirM , sayıdan başlayan nehir anlamına gelir M.
Peter Taylor

2
Bağlantılı CR.SE sorusundan, bir nehir seride hangi sayı ile başlamış gibi görünüyor, ama işte son rakam. Hangisi doğru?
Celeo

Yanıtlar:


3

C, 320294 bayt

-Std = c99 ile derleyin

#include<stdio.h>
int s(int i){for(int j=i;j;j/=10)i+=j%10;return i;}int main(){int c=0,i;while(scanf("%d",&i)){c++;if(!i)continue;int j,o[]={1,3,9},p[]={1,3,9};Q:for(j=0;j<3;j++){if(o[j]==i)goto D;else if(o[j]<i){o[j]=s(o[j]);goto Q;}}i=s(i);goto Q;D:printf("Case #%d\n\nfirst meets river %d at %d\n\n",c,p[j],o[j]);}}

Ungolfed:

#include <stdio.h>

int s(int i)
{
    for(int j = i; j; j /= 10)
        i += j % 10;
    return i;
}

int main()
{
    int c = 0, i;
    while(scanf("%d", &i))
    {
        c++;
        if(!i)
            continue;
        int j,o[]={1,3,9},p[]={1,3,9};
        Q: for(j = 0; j < 3; j++)
        {
            if(o[j] == i)
                goto D;
            else if(o[j] < i)
            {
                o[j] = s(o[j]);
                goto Q;
            }
        }
        i = s(i);
        goto Q;
        D: printf("Case #%d\n\nfirst meets river %d at %d\n\n", c, p[j], o[j]);
    }
}

Denemek!

Esasen, "hedef" nehirler, test ettiğimiz nehirden daha büyük olana kadar artırılır ve daha sonra test nehri artar. Test nehri başka bir nehire eşit olana kadar bu tekrarlanır.

Bu programdaki komut satırından parametreleri okumuyorum ve yapmanız gerekip gerekmediğinden emin değilim. Şimdi STDIN'e parametreler iletebilirsiniz. Sayısal olmayan bir girdi geçirerek sonlandırabilirsiniz.

Ayrıca lanet olsun, yarım saat dövüldü.


Şimdilik test senaryoları üzerinde çalışıyorum. Sadece 3 giriş test durumu çok uygun olmayacaktır.
Kishan Kumar

lütfen stdin'den bilgi almayı düşünür müsünüz.
Kishan Kumar

3

JavaScript (ES6)

Bu oldukça yavaş bir dil kullanarak oldukça hızlı bir cevaptır. Gerçekten, hash tabloları olan herhangi bir dili kullanmak, zamanı yürütmek sorun olmamalıdır. Tüm testlerim 100 ms'nin altında.

Giriş parametresi olarak test senaryosu listesiyle anonim yöntem.

F=cases=>{
  var t0 = +new Date
  var result = 0
  var spots = []
  var top=[,1,3,,9]
  var rivers=[,1,3,1,9,1,3,1]
  cases.forEach((n,i)=>{
    var found = result = spots[n]
    for (;!found;)
    {
      found = top.some((v,i)=>{
        for(;spots[v] |= i, v<n; top[i] = v)
          [...v+''].forEach(d=>v-=-d)
        return result = v-n ? 0 : i;
      }) || (
        [...n+''].forEach(d=>n-=-d),
        result = spots[n]
      )
    }  
    console.log(`Case #${i+1}\nfirst meets river ${rivers[result]} at ${n}`)
  })  
  return 'Time (ms) ' + (new Date-t0)
}  

console.log(F([86, 12345, 123, 456, 789, 16384]))


1

Java 7, 519505 bayt

import java.util.*;String c(int i){if(i<=0)return"";ArrayList<Long>r=f(1),s=f(3),t=f(9),x=f(i);String z="first meets river ";for(int j=0;j<r.size();j++){long u=r.get(j),v=s.get(j),w=t.get(j);if(x.contains(u))return z+1+" at "+u;if(x.contains(v))return z+3+" at "+v;if(x.contains(w))return z+9+" at "+w;}return"";}ArrayList f(long i){ArrayList<Long>l=new ArrayList();l.add(i);for(long j=0,x;j<9e4;j++){x=l.get(l.size()-1);for(char c:(x+"").toCharArray())x+=new Long(c+"");l.add(x);if(x>16383)return l;}return l;}

Evet, uzun, çirkin ve şüphesiz tamamen kod-golf daha fazla değiştirilebilir .. Hem dikkatim dağılmış ve yorgun, bu yüzden belki sadece tekrar silmek gerekir ..
Dürüst olmak oldukça zor bir meydan okumaydı. Ama en azından ilk cevabınız var ..;) (Bu orijinal orijinal C ++ programınızdan bile daha uzun olabilir .. xD)

Test edilmemiş ve test durumları:

Burada deneyin.

import java.util.*;
class M{
  static String c(int i){
    if(i <= 0){
      return "";
    }
    ArrayList<Long> r = f(1),
                    s = f(3),
                    t = f(9),
                    x = f(i);
    String z = "first meets river ",
           y = " at ";
    for(int j = 0; j < r.size(); j++){
      long u = r.get(j),
           v = s.get(j),
           w = t.get(j);
      if(x.contains(u)){
        return z+1+y+u;
      }
      if(x.contains(v)){
        return z+3+y+v;
      }
      if(x.contains(w)){
        return z+9+y+w;
      }
    }
    return "";
  }

  static ArrayList f(long i){
    ArrayList<Long> l = new ArrayList();
    l.add(i);
    for(long j = 0, x; j < 9e4; j++){
      x = l.get(l.size() - 1);
      for(char c : (x + "").toCharArray()){
        x += new Long(c+"");
      }
      l.add(x);
      if(x > 16383){
        return l;
      }
    }
    return l;
  }

  public static void main(String[] a){
    System.out.println(c(86));
    System.out.println(c(12345));
    System.out.println(c(0));
  }
}

Çıktı:

first meets river 1 at 101
first meets river 3 at 12423
(empty output)

Senin programını benimle karşılaştıracağım. Ben de çözümümü yayınlayacağım. Neden yavaş bir dil kullanılır. Herhangi bir hızlı dili kullanın.
Kishan Kumar

Ben sadece .. Hep .. Defintely kazanmak için gitmiyor burada Java 7 kod golf cevapları sonrası daha sonra hızlı algoritma etiketi fark ya kısa ya da en hızlı olsa .. Btw, senin rextester sadece uyarı vermelidir hatalara verir oyuncular / tür-başlatmalar eksikliği için .. ideone (ve Eclipse IDE) üzerinde çalışır .
Kevin Cruijssen

tamam. bir bakayım. rextester derleme zamanı ve yürütme süresi verir. Bu yüzden kullandım
Kishan Kumar

iyi bu bir sorun. Derleme süresini ve yürütme süresini veren diğer çevrimiçi derleyiciyi arayacağım
Kishan Kumar

@KishanKumar Kodumu, zaman afaik etkilememelidir alçılar ekledim İşte sonuç ile çalışan rextester kodu : Compilation time: 0.62 sec, absolute running time: 0.14 sec, cpu time: 0.11 sec, memory peak: 22 Mb, absolute service time: 0,77 secbenim için yerel olarak. Yani evet, oldukça yavaş ..
Kevin Cruijssen

1

Scala, 774 bayt

Keman: http://scalafiddle.net/console/4ec96ef90786e0f2d9f7b61b5ab0209b

Golf yapmak istemiyorum. 50ms içinde ortaya çıkan soruna bir çözüm bulur

Kullanım tam olarak istediğiniz şey olmayabilir:

scala river.scala

Artık sayıları sürekli olarak girip ardından bir enter girebilirsiniz. Ve programı 0 ile bitirin. Sonuç, enter tuşuna basar basmaz yazdırılır.

io.Source.stdin.getLines.map(_.toInt)
  .takeWhile(_ != 0)
  .map(stream(_).takeWhile(_ < 16383))
  .zipWithIndex
  .map { cur =>
    Seq(1, 3, 9).map { i =>
      val s = stream(i).takeWhile(_ < 16383)
      (cur._2+1, i, s.intersect(cur._1).headOption)
    }
  }.foreach { opts =>
    val options = opts.filterNot(_._3.isEmpty)

    if(options.isEmpty) {
      println("No result")
    } else {
      val opt = options(0)
      println(s"Case #${opt._1}\n\nfirst meets ${opt._2} at ${opt._3.get}\n\n")
    }
  }

def stream(i:Int): Stream[Int] = {
  def sub: Int => Stream[Int] = {
    i => i #:: sub(a(i))
  }
  sub(i)
}

def a(i:Int): Int = i + i.toString.map{_.asDigit}.sum

Scala hakkında fazla bir şey bilmiyorum. Lütfen rextester.com/l/scala_online_compiler
Kishan Kumar

Oraya koymaya çalıştım ama derlerken zaman aşımına uğradı.
AmazingDreams

@AmazingDreams
Kishan Kumar

@KishanKumar bile varsayılan bir kez dışarı böylece site scala için kırık gibi görünüyor
AmazingDreams

@KisthanKumar Bunu kullanın scalafiddle.net/console/4ec96ef90786e0f2d9f7b61b5ab0209b stdin'i desteklemese de bazı küçük şeyleri değiştirmek zorunda kaldım.
AmazingDreams

1

C, 228283 300 bayt

Bu, Yakov'un nehir desenlerinden yararlanmak için kodunun bir modudur. Bu ~ 3 kat daha hızlı yapar. Ayrıca, imzasız tamsayılar cltod64 bit makinelerde cezayı önler , bu yüzden birkaç bayt daha uzun ama kesirli olarak daha hızlıdır.

#define sum(z) for(y=z;y;y/=10)z+=y%10;
n,x;main(){unsigned i,j,y;while(scanf("%d",&i)){if(i){j=x=1+!(i%3)*2+!(i%9)*6;do{while(j<i)sum(j)}while(j^i&&({sum(i)i;}));printf("Case #%u\n\nfirst meets river %u at %u\n\n",++n,x,i);}}}

Ungolfed:

#define sum(z) for(y=z;y;y/=10)z+=y%10;
n, x;
main() {
    unsigned i, j, y;
    while(scanf("%d", &i)) {
        if(i){
            j = x = 1 + !(i%3)*2 + !(i%9)*6;
            do{
                while (j < i) sum(j)
            }
            while(j^i&&({sum(i)i;}));
            printf("Case #%u\n\nfirst meets river %u at %u\n\n", ++n, x, i);
        }
    }
}

Açıklama:

j = x = 1 + !(i%3)*2 + !(i%9)*6;

Bu doğru nehri seçer. Nehir 1 diğer nehirlerle buluşur, bu yüzden bunu geri dönüş vakası olarak kullanırız. Eğer 3 test nehrinin en büyük ortak böleni ise, 3 nolu nehri seçiyoruz ( 1 + !(i%3)*2). 9, test nehrinin en büyük ortak böleni ise, önceki değerleri geçersiz kılar ve 9 nehri seçeriz.

Bu neden işe yarıyor? Nehir 9, 18, 27, 36 vb. Nehir 3'te 3 katları her zaman adım olacaktır: 9 katları olan nehirler iken vb 3, 6, 12, 15, 21, ayrıca 3'ün tam katı, sadece bırakarak ilk nehir 9 olarak seçmek Kalanlar ilk önce 1. nehir ile buluşacaktır: 1, 2, 4, 8, 16, 23, 28 vb.

Doğru nehirimizi seçtikten sonra, iki ırmakla buluşana kadar adım atıyoruz.


1

Python 3, 144 bayt

r,a,b,c,i={int(input())},{1},{3},{9},1
while i:
  for x in r,a,b,c:t=max(x);x|={sum(int(c)for c in str(t))+t}
  if r&(a|b|c):i=print(*r&(a|b|c))

0

C

Çok basit, sadece o kadar uzun görünüyor çünkü 3 nehri de açtım. İlk önce 3 nehri oluşturur RIVER_LENGTH(ki umarım yeterince büyüktür) ve daha sonra her adım için Nherhangi birinde olup olmadığını görmek için her üç akışın da ikili bir arama yapar. Bu, akışlar zaten sıralandığı için çalışır, böylece içerdiği check-in log(n)saatini yapabiliriz.

#include <stdio.h>

#define RIVER_LENGTH 10000

int main() {
    int num_cases;
    scanf("%d", &num_cases);
    int cases[num_cases];
    int N;
    int s1[RIVER_LENGTH] = {1};
    int s3[RIVER_LENGTH] = {3};
    int s9[RIVER_LENGTH] = {9};
    int i;
    int temp;

    for (i = 1; i < RIVER_LENGTH; i++) {
        s1[i] = temp = s1[i-1];
        while (temp) {
            s1[i] += temp % 10;
            temp /= 10;
        }
    }

    for (i = 1; i < RIVER_LENGTH; i++) {
        s3[i] = temp = s3[i-1];
        while (temp) {
            s3[i] += temp % 10;
            temp /= 10;
        }
    }

    for (i = 1; i < RIVER_LENGTH; i++) {
        s9[i] = temp = s9[i-1];
        while (temp) {
            s9[i] += temp % 10;
            temp /= 10;
        }
    }

    int start;
    int end;
    int pivot;

    for (i=1; i <= num_cases; i++) {
        scanf("%d", &cases[i]);
    }

    for (i=1; i <= num_cases; i++) {
        printf("Case #%d\n\n", i);
        N = cases[i];

        while (1) {

            temp = N;
            while (temp) {
                N += temp % 10;
                temp /= 10;
            }

            start = 0;
            end = RIVER_LENGTH;
            pivot = 1;

            while (end != start && pivot != RIVER_LENGTH - 1) {
                pivot = start + ((end - start) >> 1);
                if (s1[pivot] == N) {
                    printf("first meets river 1 at %d\n\n", N);
                    goto case_done;
                } else if (N < s1[pivot]){
                    end = pivot;
                } else {
                    start = pivot+1;
                }
            }

            start = 0;
            end = RIVER_LENGTH;
            pivot = 1;

            while (end != start && pivot != RIVER_LENGTH - 1) {
                pivot = start + ((end - start) >> 1);
                if (s3[pivot] == N) {
                    printf("first meets river 3 at %d\n\n", N);
                    goto case_done;
                } else if (N < s3[pivot]){
                    end = pivot;
                } else {
                    start = pivot+1;
                }
            }

            start = 0;
            end = RIVER_LENGTH;
            pivot = 1;

            while (end != start && pivot != RIVER_LENGTH - 1) {
                pivot = start + ((end - start) >> 1);
                if (s9[pivot] == N) {
                    printf("first meets river 9 at %d\n\n", N);
                    goto case_done;
                } else if (N < s9[pivot]){
                    end = pivot;
                } else {
                    start = pivot+1;
                }
            }
        }

        case_done:;

    }
}

0Girdilerin sonunu sınırlamak yerine ilk önce vaka sayısı için bir sayı gerekir , çünkü biliyorsunuz, C. Bu sadece kolaylık sağlamak için ve gerçekten hiçbir şey etkilemez, bu yüzden umarım tamamdır.


Bu program, girişlerde ideone üzerinde bir zaman sınırını aştı 86.112345,0
Kishan Kumar

ideone.com/mHCeef bağlantı burada. Ve rextester bir öldürme sinyali verir
Kishan Kumar

@KishanKumar Girdilerin sonunu sınırlamak için 0 kullanmak yerine, ilk önce vaka sayısı için bir sayı gerekir, çünkü biliyorsunuz, C.
16'da Maltysen

@KishanKumar bunun yerine bunu deneyin: rextester.com/XRJK89444
Maltysen

tamam. Sorun değil. Ama programınız için fazladan bir komut dosyası yazmam gerekecek. Tüm girdi aralığının ortalama zamanını almak zorunda olduğum için.
Kishan Kumar
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.