C, 320 294 bytes

3

C, 320 294 bytes

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

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

Experimente!

Essencialmente, os rios "alvo" são aumentados até que sejam maiores que o rio contra o qual estamos testando e depois o rio de teste aumenta. Isso é repetido até que o rio de teste seja igual a outro rio.

Não estou lendo parâmetros na linha de comando deste programa e não tenho certeza se você deveria. Agora você pode passar parâmetros para STDIN. Você pode finalizar passando uma entrada não numérica.

Também danado, espancado por meia hora.


fonte
Estou trabalhando em casos de teste por enquanto. Apenas 3 casos de teste de entrada não serão muito adequados.
Kishan Kumar
por favor, você se importaria de receber informações de stdin.
Kishan Kumar

Respostas:

3

JavaScript (ES6)

Esta é uma resposta bastante rápida, usando uma linguagem bastante lenta. Realmente, o tempo de execução não deve ser um problema ao usar qualquer idioma com tabelas de hash. Todos os meus testes com menos de 100 ms.

Método anônimo com a lista de casos de teste como parâmetro de entrada.

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

edc65
fonte
1

Java 7, 519 505 bytes

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

Sim, é longo, feio e sem dúvida pode ser completamente alterado para codificá-lo mais .. Estou ao mesmo tempo distraído e cansado, talvez devesse excluí-lo novamente ..
Foi um desafio muito difícil ser honesto. . Mas pelo menos você tem sua primeira resposta ..;) (que pode até ser maior que o seu programa C ++ original e não destruído .. xD)

Casos não testados e de teste:

Experimente aqui.

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

Resultado:

first meets river 1 at 101
first meets river 3 at 12423
(empty output)
Kevin Cruijssen
fonte
Vou comparar o seu programa com o meu. Também vou postar minha solução. Por que usar uma linguagem lenta. Use qualquer linguagem rápida.
Kishan Kumar
Eu só notei a tag do algoritmo mais rápido mais tarde .. Eu sempre posto respostas de código-golfe do Java 7 aqui .. Definitivamente, não vai ganhar nem no menor nem no mais rápido. Mas, o rextester comete erros quando só deve dar avisos por falta de projeções / inicializações de tipo .. Funciona em ideone (e no Eclipse IDE).
Kevin Cruijssen
Está bem. deixe-me ver. O rextester fornece tempo de compilação e tempo de execução. Então eu usei
Kishan Kumar
Bem, isso é um problema aqui. Vou procurar outro compilador on-line que dá o tempo e execução tempo de compilação
Kishan Kumar
@KishanKumar Adicionei as transmissões no meu código, o que não deve afetar o tempo. Aqui está o código do rextester em funcionamento com o resultado: 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 secpara mim localmente. Então, sim, é muito lento ..
Kevin Cruijssen
1

Scala, 774 bytes

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

Não sinto vontade de jogar golfe. Encontra uma solução para o problema colocado dentro de 50ms

O uso pode não ser exatamente o que você deseja:

scala river.scala

Agora você pode inserir continuamente números seguidos de um enter. E encerre o programa com 0. O resultado será impresso assim que você pressionar 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
AmazingDreams
fonte
Eu não sei muito sobre Scala. Então, por favor você pode modificar o código que vai de acordo com rextester.com/l/scala_online_compiler
Kishan Kumar
Tentei colocá-lo lá, mas o tempo limite foi excedido durante a compilação.
AmazingDreams
ok @AmazingDreams
Kishan Kumar
@KishanKumar mesmo o padrão vezes fora de modo que o site parece estar quebrado para scala
AmazingDreams
@KisthanKumar Use este scalafiddle.net/console/4ec96ef90786e0f2d9f7b61b5ab0209b, mas ele não suporta stdin, então tive que mudar algumas coisas menores.
AmazingDreams
1

C, 228283 300 bytes

Este é um mod do código de Yakov para tirar proveito dos padrões do rio. Isso torna ~ 3x mais rápido. Além disso, números inteiros não assinados evitam a cltodpenalidade em máquinas de 64 bits, portanto, são alguns bytes mais longos, mas um pouco mais rápidos.

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

Explicação:

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

Isso seleciona o rio correto. O rio 1 encontra todos os outros rios, por isso usamos isso como caso de reserva. Se 3 é o maior divisor comum do rio de teste, selecionamos o rio 3 ( 1 + !(i%3)*2). Se 9 é o maior divisor comum do rio de teste, substituímos os valores anteriores e selecionamos o rio 9.

Por que isso funciona? O rio 9 vai 9, 18, 27, 36, etc. Isso dá um múltiplo de 9 a cada vez, portanto, sempre será o caminho mais curto para um rio irmão. O rio 3 passa por um múltiplo de 3 a cada vez: 3, 6, 12, 15, 21, etc. Embora os rios que são múltiplos de 9 também sejam múltiplos de 3, nós os escolhemos como o rio 9 primeiro, deixando apenas o múltiplos de 3. O restante encontrará o rio 1 primeiro: 1, 2, 4, 8, 16, 23, 28, etc.

Depois de selecionarmos o rio correto, pisamos nos dois até que eles se encontrem.

Seth
fonte
1

Python 3, 144 bytes

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))
Trelzevir
fonte
0

C

Muito simples, parece tão longo porque eu desenrolei todos os 3 rios. Primeiro ele gera os 3 rios até RIVER_LENGTH(o que eu espero que seja grande o suficiente) e, em seguida, para cada etapa, Nele faz uma pesquisa binária nos três fluxos para ver se está em algum deles. Isso funciona porque os fluxos já estão classificados, para que possamos fazer o check-in contém o log(n)tempo.

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

    }
}

É preciso um número para o número de casos primeiro, em vez de usar 0para delimitar o final das entradas, porque você sabe, C. Isso é apenas por conveniência e realmente não afeta nada, por isso espero que esteja tudo bem.

Maltysen
fonte
Este programa atinge um limite de tempo excedido na ideone de insumos 86,12345,0
Kishan Kumar
ideone.com/mHCeef aqui está o link. E dá uma saída de sinal matar em rextester
Kishan Kumar
@KishanKumar É necessário um número para o número de casos primeiro, em vez de usar 0 para delimitar o final das entradas, porque você sabe, C. Isso é apenas por conveniência e realmente não afeta nada, por isso espero que esteja tudo bem.
Maltysen
@KishanKumar tente este em vez disso: rextester.com/XRJK89444
Maltysen
está certo. Sem problemas. Mas vou ter que escrever um script extra para o seu programa. Como eu tenho que levar o tempo médio de toda a faixa de entrada.
Kishan Kumar