Digital River (Giải pháp ngắn nhất và nhanh nhất)


9

Đây là câu hỏi đầu tiên của tôi, vì vậy tôi hy vọng nó diễn ra tốt đẹp.

Lý lịch:

Đó không phải là những dòng sông mà bạn có thể nghĩ đến. Câu hỏi xoay quanh khái niệm sông kỹ thuật số. Một dòng sông kỹ thuật số là một chuỗi các số mà số sau đây nncộng tổng các chữ số của nó.

Giải trình:

12345 được theo sau bởi 12360 kể từ 1 + 2 + 3 + 4 + 5 = 15 và do đó 12345 + 15 cho 12360. tương tự 145 được theo sau bởi 155. Nếu số đầu tiên của một dòng sông kỹ thuật số, Mchúng ta sẽ gọi nó là sông M.

Ví dụ: Sông 480 là dãy bắt đầu {480,492,506,519 ....} và sông 483 là dãy bắt đầu {483,498,519, ....}. Các dòng sông và sông thông thường có thể gặp nhau, và điều tương tự cũng đúng với các dòng sông kỹ thuật số. Điều này xảy ra khi hai con sông kỹ thuật số chia sẻ một số giá trị giống nhau.

Thí dụ:

Sông 480 gặp sông 483 ở 519. Sông 480 gặp sông 507 ở 507 và không bao giờ gặp sông 480. Mỗi dòng sông kỹ thuật số cuối cùng sẽ gặp sông 1, sông 3 hoặc sông 9.

Viết chương trình có thể xác định cho một số nguyên cho trước ngiá trị nơi sông nlần đầu tiên gặp một trong ba con sông này.

Đầu vào

Đầu vào có thể chứa nhiều trường hợp thử nghiệm. Mỗi trường hợp thử nghiệm chiếm một dòng riêng và chứa một số nguyên n( 1 <= n <= 16384). Một trường hợp thử nghiệm có giá trị 0cho nchấm dứt đầu vào và kiểm tra trường hợp này phải không được xử lý.

Đầu ra

Đối với mỗi trường hợp thử nghiệm trong đầu ra đầu tiên, số trường hợp thử nghiệm (bắt đầu từ 1) như được hiển thị trong đầu ra mẫu. Sau đó, trên một dòng đầu ra riêng biệt, dòng "đầu tiên gặp sông x tại y". Ở đây y là giá trị thấp nhất trong đó sông nlần đầu tiên gặp sông x(x = 1 hoặc 3 hoặc 9). Nếu sông ngặp sông xynhiều hơn một giá trị x, xuất giá trị thấp nhất. In một dòng trống giữa hai trường hợp thử nghiệm liên tiếp.

Trường hợp thử nghiệm

Đầu vào:

86
12345
0

Đầu ra:

Case #1

first meets river 1 at 101

Case #2

first meets river 3 at 12423

Ghi điểm:

Thuật toán nhanh nhất chiến thắng. Trong trường hợp cà vạt. Người nào có mã ngắn hơn sẽ thắng.

Cảm ơn mbomb007 đã chỉ ra lỗi của tôi.

ps: Tôi muốn có giải pháp nhanh nhất chứ không phải giải pháp nhỏ nhất. Tôi cũng có một giải pháp của tôi là chậm. Đối với cái nhìn ở đây .

Ghi chú:

Tôi sẽ sử dụng điều này để kiểm tra mã. Và kiểm tra hiệu suất.


3
Tôi không chắc rằng bạn có thể ghi bàn theo cách đó. Nếu mã của ai đó là O (log (log n)) thì sao? Bạn không thể bao quát tất cả, vì vậy bạn chỉ cần nói rằng thuật toán nhanh nhất sẽ thắng, nhưng trong trường hợp hòa, mã ngắn nhất sẽ thắng và lần đầu tiên được đăng trong trường hợp cả hai đều có cùng độ dài.
mbomb007

3
Tôi không thể tìm thấy bất cứ điều gì về bản quyền hoặc khả năng sử dụng của các thách thức ACM-ICPC cũ, nhưng tôi có thể tìm thấy thử thách này trên trang lưu trữ. Được phép sử dụng ở đây?
Geobits

1
Điều đó không liên quan gì đến bản quyền. Nếu nghi ngờ, điều dễ nhất thường là gửi email cho (các) chủ sở hữu trang web và hỏi.
Geobits

3
" Nếu chữ số cuối cùng của một dòng sông kỹ thuật số, Mchúng ta sẽ gọi nó là dòng sôngM " không có nghĩa vì hai lý do: thứ nhất, nếu một dòng sông là một dãy số vô hạn thì nó không có chữ số cuối; và thứ hai, trong đoạn sôngM tiếp theo có nghĩa là dòng sông bắt đầu từ số M.
Peter Taylor

2
Từ câu hỏi CR.SE được liên kết, có vẻ như một dòng sông là số nào bắt đầu bằng chuỗi, nhưng đây là chữ số cuối cùng. Cái nào đúng?
Celeo

Câu trả lời:


3

C, 320 294 byte

Biên dịch với -std = c99

#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]);}}

Ung dung:

#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]);
    }
}

Hãy thử nó!

Về cơ bản, các dòng sông "mục tiêu" được tăng lên cho đến khi chúng lớn hơn dòng sông mà chúng tôi đang thử nghiệm và sau đó, dòng sông thử nghiệm được tăng lên. Điều này được lặp lại cho đến khi dòng sông thử nghiệm bằng với một số dòng sông khác.

Tôi không đọc các tham số từ dòng lệnh trong chương trình này và tôi không chắc liệu bạn có phải không. Bây giờ bạn có thể truyền tham số cho STDIN. Bạn có thể chấm dứt bằng cách chuyển một đầu vào không phải là số.

Cũng chết tiệt, bị đánh bởi nửa giờ.


Tôi đang làm việc trên các trường hợp thử nghiệm bây giờ. Chỉ có 3 trường hợp kiểm tra đầu vào sẽ không phù hợp.
Kishan Kumar

xin vui lòng bạn sẽ lấy đầu vào từ stdin.
Kishan Kumar

3

JavaScript (ES6)

Đây là một câu trả lời khá nhanh bằng cách sử dụng một ngôn ngữ khá chậm. Thực sự, thời gian thực hiện không phải là vấn đề khi sử dụng bất kỳ ngôn ngữ nào với bảng băm. Tất cả các bài kiểm tra của tôi dưới 100 ms.

Phương thức ẩn danh với danh sách trường hợp thử nghiệm làm tham số đầu vào.

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, 519 505 byte

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;}

Vâng, nó dài, xấu và không nghi ngờ gì có thể được thay đổi hoàn toàn thành môn đánh gôn nhiều hơn .. Tôi vừa mất tập trung vừa mệt mỏi, vì vậy có lẽ tôi nên xóa nó một lần nữa ..
Thành thật là một thử thách khá khó khăn. . Nhưng ít nhất bạn có câu trả lời đầu tiên của mình ..;) (Điều này thậm chí có thể dài hơn chương trình C ++ không được ban đầu của bạn .. xD)

Các trường hợp bất khả kháng & thử nghiệm:

Hãy thử nó ở đây.

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));
  }
}

Đầu ra:

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

Tôi sẽ so sánh chương trình của bạn với của tôi. Tôi cũng sẽ đăng giải pháp của tôi quá. Tại sao phải sử dụng một ngôn ngữ chậm. Sử dụng bất kỳ ngôn ngữ nhanh.
Kishan Kumar

Tôi chỉ nhận thấy thẻ thuật toán nhanh nhất sau này .. Tôi luôn đăng các câu trả lời golf mã Java 7 ở đây .. Chắc chắn sẽ không giành chiến thắng dù ngắn nhất hay nhanh nhất .. Btw, rextester của bạn đưa ra lỗi khi chỉ đưa ra cảnh báo vì thiếu phôi / khởi tạo kiểu .. Nó hoạt động trên ideone (và trong IDE Eclipse).
Kevin Cruijssen

đồng ý. Hãy để tôi xem. rextester cho thời gian biên dịch và thời gian thực hiện. Vì vậy, tôi đã sử dụng nó
Kishan Kumar

đó là một vấn đề ở đây Tôi sẽ tìm kiếm trình biên dịch trực tuyến khác cung cấp thời gian biên dịch và thời gian thực hiện
Kishan Kumar

@KishanKumar Tôi đã thêm các phôi trong mã của mình, điều này không ảnh hưởng đến thời gian afaik Đây là mã rextester hoạt động với kết quả: 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 seccho tôi tại địa phương. Vì vậy, vâng, nó khá chậm ..
Kevin Cruijssen

1

Scala, 774 byte

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

Tôi không cảm thấy thích chơi gôn. Nó tìm ra giải pháp cho vấn đề đặt ra trong vòng 50ms

Cách sử dụng có thể không chính xác như bạn muốn:

scala river.scala

Bây giờ bạn có thể liên tục nhập số theo sau là một nhập. Và kết thúc chương trình với 0. Kết quả sẽ được in ngay khi bạn nhấn enter.

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

Tôi không biết nhiều về Scala. Vì vậy, vui lòng bạn có thể sửa đổi mã theo rextester.com/l/scala_online_compiler
Kishan Kumar

Tôi đã cố gắng đặt nó ở đó nhưng nó đã hết thời gian trong khi biên dịch.
AmazingDreams

ok @AmazedDreams
Kishan Kumar

@KishanKumar thậm chí mặc định một lần ra ngoài vì vậy trang web dường như bị phá vỡ cho scala
AmazingDreams

@KisthanKumar Sử dụng một scalafiddle.net/console/4ec96ef90786e0f2d9f7b61b5ab0209b nó không hỗ trợ stdin mặc dù vậy tôi đã phải thay đổi một số điều nhỏ.
AmazingDreams

1

C, 228 283 300 byte

Đây là một bản sửa đổi mã của Yakov để tận dụng các mẫu sông. Điều này làm cho nó nhanh hơn gấp 3 lần. Ngoài ra, các số nguyên không dấu tránh cltodhình phạt trên các máy 64 bit, do đó, nó dài hơn một vài byte nhưng nhanh hơn một chút.

#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);}}}

Ung dung:

#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);
        }
    }
}

Giải trình:

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

Điều này chọn sông chính xác. Sông 1 gặp mọi con sông khác, vì vậy chúng tôi sử dụng trường hợp này như trường hợp dự phòng. Nếu 3 là ước số chung lớn nhất của sông thử nghiệm, chúng ta chọn sông 3 ( 1 + !(i%3)*2). Nếu 9 là ước số chung lớn nhất của dòng sông thử nghiệm, chúng tôi sẽ ghi đè các giá trị trước đó và chọn sông 9.

Tại sao điều này làm việc? Sông 9 đi 9, 18, 27, 36, v.v ... Đây là bước của bội số 9 mỗi lần, do đó, nó sẽ luôn là con đường ngắn nhất đến sông chị em. Mỗi lần sông 3 sẽ nhân bội số 3: 3, 6, 12, 15, 21, v.v ... Trong khi các sông có bội số 9 cũng là bội số của 3, chúng tôi chọn chúng là sông 9 trước, chỉ để lại sông bội số của 3. Phần còn lại sẽ gặp sông 1 trước: 1, 2, 4, 8, 16, 23, 28, v.v.

Khi chúng tôi đã chọn đúng dòng sông của mình, chúng tôi bước hai con sông cho đến khi chúng gặp nhau.


1

Python 3, 144 byte

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

Rất đơn giản, nó trông có vẻ dài bởi vì tôi đã bỏ cả 3 con sông. Đầu tiên, nó tạo ra 3 con sông lên đến RIVER_LENGTH(mà tôi hy vọng là đủ lớn), và sau đó cho mỗi bước trên Nnó thực hiện tìm kiếm nhị phân trên cả ba luồng để xem nó có nằm trong bất kỳ dòng nào không. Điều này hoạt động vì các luồng đã được sắp xếp, vì vậy chúng tôi có thể thực hiện kiểm tra chứa log(n)thời gian.

#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:;

    }
}

Trước tiên, phải mất một số cho số trường hợp, thay vì sử dụng 0để phân định phần cuối của đầu vào, bởi vì bạn biết, C. Điều này chỉ để thuận tiện và không thực sự ảnh hưởng đến bất cứ điều gì, vì vậy tôi hy vọng nó ổn.


Chương trình này đạt giới hạn thời gian vượt quá ideone trên đầu vào 86.12345,0
Kishan Kumar

ideone.com/mHCeef ở đây là liên kết. Và nó cho ra tín hiệu tiêu diệt trên rextester
Kishan Kumar

@KishanKumar Trước tiên, cần một số lượng cho các trường hợp, thay vì sử dụng 0 để phân định kết thúc đầu vào, bởi vì bạn biết, C. Điều này chỉ để thuận tiện và không thực sự ảnh hưởng đến bất cứ điều gì, vì vậy tôi hy vọng nó ổn.
Maltysen

@KishanKumar hãy thử cái này thay thế: rextester.com/XRJK89444
Maltysen

Ổn mà. Không vấn đề gì. Nhưng tôi sẽ phải viết thêm một kịch bản cho chương trình của bạn. Vì tôi phải mất thời gian trung bình của tất cả các phạm vi đầu vào.
Kishan Kumar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.