Duas estradas divergiam em uma madeira amarela (parte 2)


25

Este é o segundo de uma série, o terceiro é Duas estradas divergindo em uma madeira amarela (parte 3)

Isso é baseado em duas estradas divergindo em uma madeira amarela (parte 1) , um desafio anterior da minha. Foi bastante bem recebido, mas também foi bastante trivial (uma resposta Java em 52 bytes!) Então, fiz algo mais complexo ...

A inspiração

Este desafio é inspirado no famoso poema de Robert Frost, "The Road Not Taken":

Duas estradas divergiam em um bosque amarelo.
E , desculpe, eu não podia viajar pelas duas.
E ser um viajante, por muito tempo eu fiquei.
E olhei para uma delas o mais longe que pude
.

... 2 parágrafos aparados ...

Vou contar isso com um suspiro
Em algum lugar, eras e eras daqui em diante :
duas estradas divergiam em um bosque, e eu -
eu peguei a menos percorrida,
e isso fez toda a diferença.

Observe a penúltima linha I took the one less traveled by,,. Seu objetivo é encontrar a estrada menos percorrida em sua entrada de string. Você deve emitir um dos 2 valores que são distintos um do outro que sinalizam em que direção você deve virar para pegar a estrada menos percorrida. Uma vez que a estrada bifurca (a trilha dos hexágonos muda para números), você está no cruzamento. A partir daí, haverá 2 caminhos compostos por dígitos. O caminho cujos dígitos têm a menor soma será o caminho não percorrido. Observe que a estrada não percorrida pode ter um caminho maior, mas uma soma menor. Aqui estão alguns exemplos / casos de teste de um programa que imprime "left" ou "right" para o caminho não percorrido:

 1     2
  1   2
   1 2
    #
    #
    #
left (3 < 6)


 1     2
  2   2
   1 1
    #
    #
    #
left (4 < 5)


 12    2
  11  2
   1 1
    #
    #
    #
right (6 > 5)


 99   989
  99  89
  99 99
  99 99
    #
    #
    #
   # 
left (72 < 79)


1111 1110
 001 111
  11 11
  11 11
    #
   ##
  ##
 ##  
left (9 < 10) (Note: 1111 is interpreted as 1+1+1+1=4, not 1111=1111)


1       1
 0     1
  1   1
  1   1
  1   1
  1   1
   1 1 
    #
    #
    #
     #
      #
left (6 < 7)


1   1 
 0   1  
  1   1
  1   1
  1   1
  1   1
   1 1 
    #
    #
    #
     #
      #
left (6 < 7)

Coisas para assumir e lembrar

  • Sempre haverá 2 caminhos. Nem mais nem menos.
  • Você pode obter a entrada do STDIN uma linha de cada vez, uma sequência contendo caracteres LF ou uma sequência contendo uma barra invertida literal e um n. Se você precisar de alguma outra forma, peça aprovação nos comentários.
  • Você não precisa se preocupar com entradas inválidas ou caminhos vinculados. Esses nunca serão inseridos no seu programa / função.
  • A entrada pode ter qualquer comprimento em largura ou altura, menor que o limite de caracteres do seu idioma.
  • Nunca haverá um #e um número na mesma linha.
  • Todos os dígitos no caminho são números inteiros positivos de 0 a 9.
  • Entrada ou saída com uma nova linha à direita é permitida.
  • Veja minha resposta JS ES6 abaixo para um exemplo.
  • Sempre haverá pelo menos 1 espaço entre os 2 caminhos.
  • Os 2 caminhos sempre terão a mesma altura para cada mapa, mas podem ser diferentes em outros mapas.
  • Se você está confuso sobre um caso de teste específico, por favor me diga.
  • 1111 é interpretado como 1 + 1 + 1 + 1 = 4, não 1111 = 1111. O mapa é uma série de números de um dígito, não números de comprimento arbitrário.
  • Isso é , então a resposta mais curta em bytes vence!
  • Lacunas padrão proibidas

Se você tiver alguma dúvida sobre esse desafio, pergunte-me nos comentários e boa sorte!


Ei, você pode ver todas as respostas e a contagem de bytes colando $("div > h1").map(function(){return $(this).text()}).get().join("\n");no seu console!
programmer5000

1
Aqui está uma versão alternativa com espaços em branco removido e ignorado respostas strikedthroughlet answers = $('div > h1').map(function(){return $(this).clone().children(':not(a)').remove().end().text().replace(/\s+/g,' ').trim()}).get();answers.splice(0, 1);answers.join('\n');
David Archibald

2
Um # não é um hexágono ... #
31253751

1
" mas também era bastante trivial (uma resposta Java em 52 bytes!) " 43 bytes agora. ;)
Kevin Cruijssen 30/03

Mais uma vez? Que diabos está errado com você?
Matthew Roh

Respostas:


2

05AB1E , 21 15 bytes

Saídas 0 para esquerda e 1 para direita.

|vy#õK€SO})øO`›

Experimente online!

Explicação

|v                # for each line in input
  y#              # split on spaces
    õK            # remove empty strings
      €S          # split each string into a list of chars
        O         # sum each sublist
         }        # end loop
          )ø      # wrap stack in a list and zip
            O     # sum each sublist (side of the tree)
             `›   # compare left to right

11

Retina , 28 bytes

\d
$*
%r`1\G
-
Os`.
+`-1

1+

Experimente online!

Impressões 0 para a esquerda e 1para a direita. Assume que não há espaços à direita em nenhuma linha.

Explicação

\d
$*

Converta cada dígito Nem uma sequência de Nunidades.

%r`1\G
-

Uma em cada linha ( %), combine as consecutivas ( \G) a partir do final ( r) e substitua cada uma por -(por exemplo, transforme o ramo direito em -s).

Os`.

Classifique todos os caracteres, para que todos os -s estejam diretamente na frente de todos os 1s.

+`-1

Cancele repetidamente um par de -e 1.

1+

Tente combinar pelo menos um 1(se houver, havia mais pesos no caminho esquerdo).



7

Chip , 216 bytes

 EZ,Z~.
E~]x-.|
F].>vm'
Ax]}#----------------.
Bx]}#---------------.|z.
Cx]}#------------.,Z|##' E
Dx]}#---------.,Z|`@@('A~^~t
 E.>#------.,Z|`@@-('
A~S`#v--.,Z|`@@-('
*f,--<,Z|`@@-('
e |,Z|`@@-('
,Z|`@@-('
>@@-('
a

Experimente online!

Um pouco maior que a resposta para a parte 1 ...

visão global

O chip é uma linguagem 2D inspirada nos circuitos reais e lida com os bits componentes de cada byte em um fluxo de bytes.

Esta solução mantém uma soma contínua dos dígitos que vê, invertendo o sinal da entrada cada vez que encontra um trecho de espaço em branco e terminando no primeiro #. Então, para entrada

 11   12
  2   2
   1 1
    #
    #
    #

Nós recebemos 1 + 1 - 1 - 2 + 2 - 2 + 1 - 1 = -1. O sinal do resultado é dado como saída, um número negativo produz o resultado 1e positivo é0 .

Portanto, saída de 1significa que o caminho esquerdo é menos usado e0 significa direito.

Explicação

Em um nível alto, é assim que funciona:

A diagonal principal com os @elementos é o acumulador, a saída é decidida pelo ana parte inferior. (Oito pares de@ médias de oito bits, mas o bit mais alto é o sinal, portanto, esta solução pode lidar com uma diferença máxima de +127 ou -128. Transbordar parcialmente é bom, desde que voltemos antes de terminar.)

As quatro linhas que começam como Ax]}#--... estão lendo a entrada e, no caso de um dígito, negando-a (se necessário) e passando o valor para os somadores.

As três primeiras linhas decidem se estamos olhando para um dígito ou uma sequência de espaço em branco e controlamos se os dígitos precisam ser negados.

Os elementos restantes inseridos sob as entradas e os elementos à direita tratam da condição de terminação e mapeiam a saída para ASCII (para que obtenhamos caracteres '0'ou em '1'vez de valores 0x0ou 0x1. Esse mapeamento ASCII não exigia bytes extras, caso contrário eu não incluí-lo.)


2
Gosto que o código pareça duas estradas divergentes.
Laikoni 29/03

@Laikoni Eu nem tinha notado, que é kinda cool :)
Phlarx

4

JavaScript (ES6), 55 bytes

x=>x.replace(/\d(?=.*( )|)/g,(d,s)=>t-=s?d:-d,t=0)&&t<0

Assume que não há espaços à direita em cada linha e saídas truepara right, falsepara left. O truque é combinar cada dígito na entrada e, se houver um espaço depois na mesma linha, subtraí-o do total; caso contrário, adicione-o ao total. Se o total final for menor que 0, o caminho certo será o menos percorrido e vice-versa.

Experimente:

f=x=>x.replace(/\d(?=.*( )|)/g,(d,s)=>t-=s?d:-d,t=0)&&t<0
<textarea placeholder = "paste in a map here..." oninput = "document.querySelector('div').innerText = f(this.value)"></textarea>
<div></div>


Você precisa colocar um x=no início, porque expressões não são permitidas, apenas funções armazenadas como uma variável e programas inteiros.
programmer5000

@ programmer5000 Por quê? Parece um pouco estranho substituir os padrões e não parece indicar que esse é o caso da pergunta.
Assistente de trigo

1
@ programmer5000 Na verdade, funções sem nome são permitidas por padrão . (Obrigado pelo trecho, btw)
ETHproductions

4

Python 3 , 85 94 bytes

import re
g=lambda s,i:sum(map(int,''.join(re.findall('\d+',s)[i::2])))
lambda s:g(s,0)>g(s,1)

Experimente online!

Maldições! Não leu o problema perto o suficiente. Adicionada a correção ( ''.join()), mas ao custo de 9 bytes.


Tão perto! Boa captura, obrigado!
Datastream


2

Retina , 180 bytes

A contagem de bytes assume a codificação ISO 8859-1.

^(?=( *(0|(1|(?<3>2|(?<3>3|(?<3>4|(?<3>5|(?<3>6|(?<3>7|(?<3>8|(?<3>9))))))))))+.+¶)+)(.+ (0|(?<-3>1|(?<-3>2|(?<-3>3|(?<-3>4|(?<-3>5|(?<-3>6|(?<-3>7|(?<-3>8|(?<-3>9))))))))))+¶)+ *#

Experimente online!

Eu pensei em tentar também uma solução somente regex (o acima é um regex .NET simples que corresponde apenas às entradas onde o caminho correto deve ser seguido, exceto pelo uso como abreviação de \n).

É irritantemente repetitivo, mas é o que acontece quando você precisa tratar cada dígito possível individualmente.

A solução é uma aplicação bastante direta de grupos de balanceamento : primeiro somamos os dígitos no ramo esquerdo pressionando Ncapturas na pilha 3para cada dígito N. Em seguida, tentamos alcançar o #, enquanto popping dos 3 Ntempos da pilha para cada dígito Nno ramo direito. Isso só é possível se a soma dos dígitos no ramo esquerdo for maior que a soma no ramo direito (já que você não pode sair de uma pilha vazia).


Não estou familiarizado com as expressões regulares do .NET, mas você não pode fazer um conjunto de caracteres: [0-9]para corresponder a todos os dígitos ou \d?
programmer5000

@ programmer5000 Obviamente, mas não consigo distinguir entre eles para determinar quantas capturas devo enviar para somar.
Martin Ender

2

JavaScript (ES6), 106 104 bytes

s=b=>(b=b.split`\n`,c=0,d=0,b.forEach(a=>{a=a.match(/\d+/g)||[],c+=+(a[0]?a[0]:0),d+=+(a[1]?a[1]:0)}),c<d)

s=b=>(b=b.split("\n"),c=0,d=0,b.forEach(a=>{a=a.match(/\d+/g)||[],c+=+(a[0]?a[0]:0),d+=+(a[1]?a[1]:0)}),c<d)

sé uma função que retorna truese a estrada não percorrida estiver à esquerda. Ungolfed:

var proc = function(str){
    str = str.split("\n");
    var left = 0;
    var right = 0;
    str.forEach(item=>{
        var match = item.match(/\d+/g) || [];
        console.log(match);
        left += +(match[0] ? match[0] : 0);
        right += +(match[1] ? match[1] : 0);
    });
    return left < right;
};

s=b=>(b=b.split`\n`,c=0,d=0,b.forEach(a=>{a=a.match(/\d+/g)||[],c+=+(a[0]?a[0]:0),d+=+(a[1]?a[1]:0)}),c<d)
<textarea placeholder = "paste in a map here..." oninput = "document.querySelector('div').innerText = s(this.value)"></textarea>
<div></div>


Espero que alguém possa obter uma pontuação melhor do que esta ... #
programmer5000

Desafio aceito @ programmer5000
David Archibald

@DavidArchibald alguém já fez, mas eu gostaria de receber uma nova resposta. Você está interessado no terceiro da série ?
programmer5000

certo. Não sabia que existiam 3 #
454 David Archibald #

2

PowerShell , 80 bytes

$args-split'\s|#'-ne''|%{$a+=(($i=[char[]]$_-join'+'|iex),-$i)[($x=!$x)]};$a-gt0

Experimente online!

(Apenas chiando nas respostas do Python.: D)

Saídas Truepara o caminho esquerdo eFalse para o caminho direito.

Recebe a entrada como uma string delineada com `n, que é o equivalente do PowerShell de "uma string contendo uma barra invertida literal e um n" ou como uma string multilinha literal. Em seguida, -splitinserimos essa entrada \s(espaço em branco, incluindo novas linhas) ou# filtramos todos os resultados vazios -ne'', deixando apenas uma matriz de dígitos. Aqueles são alimentados em um loop |%{...}.

A cada iteração, primeiro pegamos o elemento atual $_, o convertemos como uma charmatriz, -joinjuntamente com um sinal de mais +e o canalizamos iex(abreviado para Invoke-Expressione semelhante a eval). Está armazenado em, $ipara que possamos resumir corretamente os dígitos nesse pedaço específico do caminho. Em seguida, usamos isso e seu negativo como os dois elementos de uma matriz ($i, -$i), indexados ao inverter um valor booleano para frente e para trás. Ou seja, a primeira iteração nesse loop, o primeiro bloco de caminho esquerdo, indexaremos -$i; da próxima vez, vamos levar $i; e assim por diante. Aqueles são acumulados $acom+= .

Por fim, avaliamos se $a-greater than 0. Se for, o caminho certo possui uma soma maior, caso contrário, o caminho esquerdo possui uma soma maior. Esse resultado booleano é deixado no pipeline e a saída é implícita.


2

CJam , 19 18 bytes

qN/Sf%z{'1*:~:+}/>

Experimente online!

Imprime 0para esquerda e1 para a direita.

Explicação

q      e# Read all input.
N/     e# Split into lines.
Sf%    e# Split each line around runs of spaces.
z      e# Transpose to group each branch.
       e# Note that each branch will have the same number of digit segments
       e# now but the first branch will also have all the #s at the end in
       e# separate segments.
{      e# For each branch...
  '1*  e#   Join the segments into a single string with 1s as separators.
       e#   This will add the same number of 1s between digit segments in
       e#   both branches (which won't affect their relative sum) and it 
       e#   will also insert a 1 before each # in the first branch.
  :~   e#   Evaluate each character. The digit characters are simply turned
       e#   into their values, but # is the exponentiation operator in CJam.
       e#   This is why we inserted those additional 1s, because 1# is a no-op.
  :+   e#   Sum the digits in the branch.
}/
>      e# Check whether the left branch's sum is greater than the right one's.

1

Mathematica, 80 77 bytes

Agradecemos a Martin Ender por economizar 3 bytes!

#<#2&@@Total@Partition[Tr/@ToExpression[Characters@StringSplit@#/."#"->0],2]&

Função pura pegando uma string delimitada por nova linha como entrada e retornando Truepara pegar o caminho esquerdo, Falsepara pegar o caminho certo. Malditos nomes de comandos longos do Mathematica; isso é como 10 fichas.


0

Pip , 19 18 bytes

LR+XDax:-x+$+$0SGx

Recebe a entrada como uma única string na linha de comando (que precisará de aspas e escape de novas linhas se executada em uma linha de comando real). Saídas -1para esquerda, 1para direita. Experimente online!

Explicação

Faz um loop sobre execuções de dígitos, adicionando somas de dígitos a uma contagem. O sinal da contagem é trocado a cada vez, com o resultado final de que os valores à esquerda são negativos e os valores à direita são positivos. Em seguida, imprimimos o sinal da contagem final ( -1ou 1).

                    a is 1st cmdline arg; XD is regex `\d`; x is "" (implicit)
                    Note that "" in a math context is treated as 0
  +XD               Apply regex + to XD (resulting in `\d+`)
LR   a              Loop over matches of that regex in a:
             $0      Regex match variable containing the full match
           $+        Sum digits by folding on +
      x:-x+          Swap the sign of the tally and add this sum
               SGx  After the loop, print the sign of the tally

0

Haskell , 64 bytes

g=sum.map fromEnum
f(a:b:r)|a>"#"=g a-g b+f r|1<3=0
(>0).f.words

Experimente online! Uso: A função anônima (>0).f.wordsusa como argumento uma string separada por nova linha e retorna Falsepara a esquerda e Truepara a direita.

Explicação:

Dada uma entrada

 99   989
  99  89
  99 99
    #
    #
   # 

que é a cadeia " 99 989\n 99 89\n 99 99\n #\n #\n #", em seguida, wordsretira todas as novas linhas e espaços e retorna uma lista dos restantes strings: ["99","989","99","89","99","99","#","#","#"]. A função fpega os dois primeiros elementos ae bnessa lista e verifica se ahá uma sequência de dígitos comparando-a com a sequência "#". (Como o caractere '#'é menor que todos os caracteres de dígito '0', será negativo e, caso contrário, positivo para o caminho certo, portanto'1' , ... cada string que começa com um dígito será lexicographically maior do que "#".) A função gmapeia cada caractere em uma string de seu código de caracteres ASCII e retorna sua soma. Em faplicamos ga ae be computação g a - g b, que é o valor do caminho da esquerda, deduzido o valor do direito, e adicioná-lo a uma chamada recursiva parafpara lidar com as seguintes linhas. Se o caminho esquerdo for mais percorrido, o resultadof(>0) verifica se o resultado é maior que zero.


0

Python 3 , 84 bytes

Como todos os envios atuais de Python são funções, pensei em contribuir com um programa completo.

x=0
try:
 while 1:
  for n in input().split():x=-x+sum(map(int,n))
except:print(x>0)

Imprime Truese o caminho esquerdo for menos percorrido,False caso contrário. Experimente online!

Para cada linha de entrada, isso divide-se em espaço em branco, soma os dígitos de cada elemento resultante e o adiciona a uma contagem enquanto inverte o sinal da contagem a cada etapa. Ele continua lendo as linhas de entrada até atingir uma com a #, quando nesse ponto map(int,n)gera uma exceção e saímos do loop, imprimindo Truese a contagem é positiva ou Falsenão.


0

Lote, 169 bytes

@echo off
set/as=0
:l
set/pr=
if not %r: =%==# call:c - %r%&goto l
cmd/cset/a"s>>9
exit/b
:c
call:r + %3
:r
set/as%1=%2%%10,d=%2/10
if %d% gtr 0 call:r %1 %d%

Imprime 0para a esquerda e os dígitos esquerdo e direito adicionam os dígitos direitos e subtraem os dígitos esquerdos. Finalmente, o resultado é deslocado para extrair o sinal.-1 para a direita. Nota: lê as linhas até encontrar uma com a #e depois para de ler. A diferença nas somas do caminho é limitada a 511 (adicione 1 byte para suportar diferenças maiores). Não mais que 9 dígitos em cada linha de cada caminho (suporta qualquer número de linhas). Explicação: Ad sub-rotina utiliza dois parâmetros: adicionar ou subtrair e o (s) dígito (s). Ele extrai o último dígito por módulo por 10 e os dígitos restantes dividindo por 10 e se chama recursivamente enquanto ainda existem dígitos restantes. Ac sub-rotina usa três parâmetros: se deseja adicionar ou subtrair, os dígitos a serem adicionados ou subtraídos e outros dígitos a serem adicionados. Isso chama odsub-rotina para manipular os dígitos a serem adicionados e, em seguida, passa a tratar dos dois primeiros parâmetros. Isso significa que chamar a csub-rotina com os parâmetros-


0

Oitava, 46 bytes

@(a)diff((a(:)-48)'*(bwlabel(a>35)(:)==1:2))<0

Experimente online! Uma função que recebe uma matriz de caracteres 2D acomo entrada.

Explicação:

a=

    1   1  
     0   1 
      1   1
      1   1
      1   1
      1   1
       1 1 
        #  
        #  
        #  
         # 
          #

a > 35                   %convert the matrix to a binary matrix
                         %where there is a number corresponing
                         %element of the binary matrix is 1.

*   *  
 *   * 
  *   *
  *   *
  *   *
  *   *
   * * 

bwlabel(a>35)            %label each connected component. 


1   2  
 1   2 
  1   2
  1   2
  1   2
  1   2
   1 2 

B=bwlabel(a>35)(:)==1:2  % a binary `[n ,2]` matrix created 
                         % each column related to one of labels

A=(a(:)-48)'             % convert array of characters to array of numbers 

A * B                    % matrix multiplication that computes 
                         % the sum of numbers under each label

diff(A*B)<0              % check if the left is grater than the right

0

Java 7, 219 216 bytes

boolean c(String s){int l=0,r=0;for(String x:s.split("\n")){l+=f(x,0);r+=f(x,1);}return l>r;}int f(String x,int i){if(x.contains("#"))return 0;int n=0;for(int c:x.trim().split("\\s+")[i].getBytes())n+=c-48;return n;}

Pouco mais de 52 bytes neste momento. ;)
E novamente retorna falsepara a direita e truepara a esquerda.

Explicação:

boolean c(String s){              // Method with String parameter and boolean return-type
  int l=0, r=0;                   //  Right and left counters
  for(String x : s.split("\n")){  //  Loop over de lines
    l += f(x,0);                  //   Add all left digits to the left-counter
    r += f(x,1);                  //   Add all right digits to the right-counter
  }                               //  End of loop
  return l>r;                     //  Return whether the left-counter is larger than the right-counter
}                                 // End of method

int f(String x, int i){           // Separate method with String and integer parameters, and int return-type
  if(x.contains("#"))             //  If the current line contains "#"
    return 0;                     //   Simply return 0
  int n=0;                        //  Counter
  for(int c :                     //  Loop over the digits by
              x.trim()            //    first removing leading and trailing whitespaces
              .split("\\s+")      //    then split them right in the middle
              [i]                 //    then pick either the left or right side based on the int index parameter
              .getBytes())        //    and convert that String to a byte-array
    n += c-48;                    //   For each of those digit-characters: add it to the counter
                                  //  End of loop (implicit / single-line body)
  return n;                       //  Return the counter
}                                 // End of separate method

Código do teste:

Experimente aqui.

class M{
  boolean c(String s){int l=0,r=0;for(String x:s.split("\n")){l+=f(x,0);r+=f(x,1);}return l>r;}int f(String x,int i){if(x.contains("#"))return 0;int n=0;for(int c:x.trim().split("\\s+")[i].getBytes())n+=c-48;return n;}

  public static void main(String[] a){
    M m = new M();
    System.out.println(m.c(" 1     2\n  1   2\n   1 2\n    #\n    #\n    #"));
    System.out.println(m.c(" 1     2\n  2   2\n   1 1\n    #\n    #\n    #"));
    System.out.println(m.c(" 12    2\n  11  2\n   1 1\n    #\n    #\n    #"));
    System.out.println(m.c(" 99   989\n  99  89\n  99 99\n  99 99\n    #\n    #\n    #\n   # "));
    System.out.println(m.c("1111 1110\n 001 111\n  11 11\n  11 11\n    #\n   ##\n  ##\n ##  "));
    System.out.println(m.c("1       1\n 0     1\n  1   1\n  1   1\n  1   1\n  1   1\n   1 1 \n    #\n    #\n    #\n     #\n      #"));
    System.out.println(m.c("1   1 \n 0   1 \n  1   1\n  1   1\n  1   1\n  1   1\n   1 1 \n    #\n    #\n    #\n     #\n      #"));
  }
}

Saída:

false
false
true
false
false
false
false
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.