Digital River (가장 빠르고 빠른 솔루션)


9

이것이 첫 번째 질문이므로 잘 진행되기를 바랍니다.

배경:

당신이 생각하고있는 강이 아닙니다. 이 문제는 디지털 강 개념에 관한 것입니다. 디지털 강 숫자 다음 숫자의 순서입니다 n입니다 n플러스의 숫자의 합계입니다.

설명:

12345 다음에는 1 + 2 + 3 + 4 + 5 = 15이므로 12360이옵니다. 따라서 12345 + 15는 12360을 제공합니다. 마찬가지로 145 다음에 155가옵니다. 디지털 강의 첫 번째 숫자는 강 M이라고합니다 M.

예를 들어, River 480은 {480,492,507,519 ....}로 시작하는 시퀀스이고, River 483은 {483,498,519, ....}로 시작하는 시퀀스입니다. 일반 하천과 강은 만날 수 있으며 디지털 강에서도 마찬가지입니다. 이것은 두 개의 디지털 강이 동일한 값을 공유 할 때 발생합니다.

예:

480 강은 519에서 483 강과 만나고 507 강은 507에서 507 강과 만나고 481 강과 절대 만나지 않습니다. 모든 디지털 강은 결국 1 강, 3 강 또는 9 강을 만나게됩니다.

주어진 정수에 n대해 강이 n처음이 세 강 중 하나를 만나는 값을 결정할 수있는 프로그램을 작성하십시오 .

입력

입력에는 여러 테스트 사례가 포함될 수 있습니다. 각 테스트 사례는 별도의 줄을 차지하며 정수 n( 1 <= n <= 16384)를 포함합니다 . 값이 0for 인 n테스트 케이스는 입력 을 종료하며이 테스트 케이스는 처리되지 않아야합니다.

산출

입력의 각 테스트 케이스에 대해 먼저 샘플 출력에 표시된대로 테스트 케이스 번호 (1부터 시작)를 출력하십시오. 그런 다음 별도의 라인 출력에서 ​​라인은 "y에서 x 강을 처음 만납니다". 여기서 y는 강이 n처음 강을 만나는 가장 낮은 값 입니다 x(x = 1 또는 3 또는 9). 강하면 n강을 충족 x에서 y의 두 개 이상의 값에 대한 x출력 최저값. 두 개의 연속 테스트 사례 사이에 빈 줄을 인쇄하십시오.

테스트 사례

입력:

86
12345
0

산출:

Case #1

first meets river 1 at 101

Case #2

first meets river 3 at 12423

채점 :

가장 빠른 알고리즘이 승리합니다. 넥타이의 경우. 더 짧은 코드를 가진 사람이 이길 것입니다.

내 오류를 지적한 mbomb007 에게 감사합니다 .

추신 : 가장 작은 솔루션이 아닌 가장 빠른 솔루션을 원합니다. 나는 또한 느린 해결책을 가지고 있습니다. 여기 를보십시오 .

노트 :

코드 테스트에 이것을 사용할 것 입니다. 그리고 성능 검사.


3
그런 식으로 득점 할 수 있을지 모르겠습니다. 누군가의 코드가 O (log (log n))이면 어떻게됩니까? 그것들을 모두 다룰 수는 없으므로 가장 빠른 알고리즘이 승리한다고 말하면되지만, 넥타이의 경우 가장 짧은 코드가 승리하고 두 개의 길이가 같은 경우 처음으로 게시 된 승리입니다.
mbomb007

3
이전 ACM-ICPC 과제의 저작권 또는 유용성에 대한 정보는 없지만 보관 사이트 에서이 과제를 찾을 수 있습니다. 여기에서 사용할 수 있습니까?
Geobits

1
그것은 저작권과 관련이 없습니다. 확실하지 않은 경우 가장 쉬운 방법은 일반적으로 사이트 소유자에게 전자 메일을 보내고 문의하는 것입니다.
Geobits

3
" 디지털 강의 마지막 숫자가 강이라면 M우리는 그것을 강M 이라고 부를 것입니다 . 둘째, 다음 단락에서 M 은 수에서 시작하는 강을 의미합니다 M.
피터 테일러

2
연결된 CR.SE 질문에서 강은 시리즈에서 시작된 숫자 중 하나 인 것처럼 보이지만 마지막 숫자입니다. 어느 것이 맞습니까?
셀 레오

답변:


3

C, 320 294 바이트

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

언 골프 드 :

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

사용해보십시오!

기본적으로 "대상"강은 테스트중인 강보다 클 때까지 증가한 후 시험 강이 증가합니다. 이것은 시험 강이 다른 강과 같아 질 때까지 반복됩니다.

이 프로그램의 명령 줄에서 매개 변수를 읽지 못하고 있는지 확실하지 않습니다. 이제 매개 변수를 STDIN으로 전달할 수 있습니다. 숫자가 아닌 입력을 전달하여 종료 할 수 있습니다.

또한 30 분씩 때렸다.


지금은 테스트 사례를 연구 중입니다. 3 개의 입력 테스트 사례만으로는 적합하지 않습니다.
Kishan Kumar 2016

stdin에서 입력을 받아 주시겠습니까?
Kishan Kumar

3

자바 스크립트 (ES6)

이것은 매우 느린 언어를 사용하는 매우 빠른 답변입니다. 실제로 해시 테이블이있는 언어를 사용하면 실행 시간이 문제가되지 않습니다. 100ms 미만의 모든 테스트.

테스트 케이스 목록을 입력 매개 변수로 사용하는 익명 메소드.

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

자바 7, 519 505 바이트

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

예, 길고 못 생겼으며 의심 할 여지없이 코드 골프로 더 완전히 바꿀 수 있습니다. 산만하고 피곤해서 다시 삭제해야합니다.
정직한 것은 매우 어려운 도전이었습니다. 그러나 적어도 첫 번째 대답은 ..;)

언 골프 및 테스트 사례 :

여기에서 시도하십시오.

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

산출:

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

나는 당신의 프로그램을 나의 것과 비교할 것입니다. 또한 솔루션을 게시하려고합니다. 느린 언어를 사용해야하는 이유. 빠른 언어를 사용하십시오.
Kishan Kumar

난 단지 .. 난 항상 .. defintely에서 승리하기 위해 않을거야 여기에 자바 7 코드 골프 답변을 게시 이후에 가장 빠른 알고리즘 태그를 발견하거나 짧은 또는 빠른하지만 .., BTW 당신의 rextester는 단지 경고를 제공해야 할 때 오류를 제공합니다 캐스트 / 유형 초기화가 없습니다. ideone (및 Eclipse IDE)에서 작동합니다 .
Kevin Cruijssen 2016 년

확인. 보자 rextester는 컴파일 시간과 실행 시간을 제공합니다. 그래서 그것을 사용했습니다
Kishan Kumar

여기에 문제가 있습니다. 나는 컴파일 시간과 실행 시간을주는 다른 온라인 컴파일러를 찾을 것이다
Kishan Kumar

@KishanKumar 시간에 영향을 미치지 않는 코드에 캐스트를 추가했습니다. 다음은 결과 가있는 rextester 코드 입니다 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 sec. 네, 꽤 느립니다.
Kevin Cruijssen

1

스칼라, 774 바이트

바이올린 : http://scalafiddle.net/console/4ec96ef90786e0f2d9f7b61b5ab0209b

나는 골프를 좋아하지 않습니다. 50ms 이내에 제기 된 문제에 대한 해결책을 찾습니다.

사용법이 원하는 것이 아닐 수도 있습니다.

scala river.scala

이제 계속해서 숫자를 입력하고 Enter를 입력 할 수 있습니다. 그리고 0으로 프로그램을 종료하십시오. 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

스칼라에 대해 잘 몰라요. rextester.com/l/scala_online_compiler
Kishan Kumar

거기에 넣으려고했지만 컴파일하는 동안 시간이 초과되었습니다.
AmazingDreams

ok @AmazingDreams
Kishan Kumar

@KishanKumar 기본 설정도 한 번 초과되었으므로 사이트가 스칼라로 인해 망가진 것 같습니다
AmazingDreams

@KisthanKumar 사용이 하나의 scalafiddle.net/console/4ec96ef90786e0f2d9f7b61b5ab0209b 그것은 내가 몇 가지 사소한 것들을 변경했다, 그래서 비록 stdin을 지원하지 않습니다.
AmazingDreams

1

C 228 283 300 바이트

이것은 강 패턴을 활용하기위한 Yakov 코드의 한 형태입니다. 이것은 ~ 3 배 더 빠릅니다. 또한 부호없는 정수 cltod는 64 비트 컴퓨터 에서 페널티를 피 하므로 몇 바이트 더 길지만 부분적으로 빠릅니다.

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

언 골프 드 :

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

설명:

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

이것은 올바른 강을 선택합니다. 강 1은 다른 모든 강과 만나므로이를 대체 사례로 사용합니다. 3이 테스트 강의 최대 공약수 인 경우 강 3 ( 1 + !(i%3)*2)을 선택 합니다. 9가 테스트 강의 최대 공약수이면 이전 값을 무시하고 강 9를 선택합니다.

왜 이것이 작동합니까? 강 9는 9, 18, 27, 36 등으로 이동합니다. 이것은 매번 9의 배수로 증가하므로 항상 자매 강으로가는 가장 짧은 경로가됩니다. 3 번 강은 매번 3, 6, 12, 15, 21 등 3의 배수로 나옵니다. 9의 배수 인 강 또한 3의 배수 인 반면 , 우리는 먼저 강을 9로 선택합니다. 3의 배수. 나머지는 1, 2, 4, 8, 16, 23, 28 등의 강을 먼저 만나게됩니다.

올바른 강을 선택하면 두 강이 만나기 전까지 밟습니다.


1

파이썬 3, 144 바이트

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

매우 간단합니다. 3 개 강 모두를 풀었 기 때문에 그렇게 오래 보입니다. 먼저 3 개의 강을 생성합니다 RIVER_LENGTH(충분히 크길 바랍니다). 그리고 각 단계마다 N3 개 스트림 모두에서 이진 검색을 수행하여 어느 강에 있는지 확인합니다. 스트림이 이미 정렬되어 있기 때문에 작동합니다 log(n). 따라서 포함 체크인 시간을 할 수 있습니다 .

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

    }
}

0C를 알고 있기 때문에 입력의 끝을 구분하는 데 사용하는 대신 먼저 사례 수에 많은 숫자가 필요합니다 . 이는 편의상이며 실제로 아무런 영향을 미치지 않기 때문에 괜찮습니다.


이 프로그램은 입력 86,12345,0에서 이데온의 시간 제한을 초과했습니다
Kishan Kumar

ideone.com/mHCeef는 여기 링크입니다. 그리고 그것은 rextester에 킬 신호 출력을 준다
Kishan Kumar

@KishanKumar C를 알고 있기 때문에 입력의 끝을 구분하기 위해 0을 사용하는 대신 먼저 사례 수에 숫자가 필요합니다 .C. 이는 편의상이며 실제로 아무런 영향을 미치지 않기 때문에 괜찮습니다.
Maltysen 2016 년

@KishanKumar 대신 이것을 시도하십시오 : rextester.com/XRJK89444
Maltysen

괜찮아. 문제 없어요. 그러나 나는 당신의 프로그램을 위해 여분의 스크립트를 작성해야 할 것입니다. 모든 입력 범위의 평균 시간이 필요합니다.
Kishan Kumar 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.