Validar um gráfico de caule e folhas

20

Um gráfico de caule e folha exibe vários valores numéricos em grupos, que são determinados por todos, exceto o último dígito. Por exemplo, suponha que tenhamos esse conjunto de dados:

0, 2, 12, 13, 13, 15, 16, 20, 29, 43, 49, 101

Nós poderíamos produzir este tronco e folha plot:

0|02
1|23356
2|09
3|
4|39
5|
6|
7|
8|
9|
10|1

O caule da primeira linha é 0, então suas "folhas" - os dígitos após o |- representam os valores entre 0 inclusivo e 10 exclusivo. As folhas em cada haste são classificadas. Hastes sem folhas (como 3) ainda aparecem na plotagem. O valor de 101 está entre 100 inclusivo e 110 exclusivo, portanto, seu tronco é 10 (100 dividido por 10).

Seu desafio é verificar se um pedaço de texto é um gráfico de caule e folha válido. Um gráfico válido satisfaz estas regras:

  • Possui exatamente uma linha para cada haste (ou seja, grupo com 10 largos) no intervalo de dados (incluindo hastes no meio do intervalo sem folhas)
  • Não tem hastes fora do intervalo
  • Todas as folhas são ordenadas ascendendo à direita
  • Todas as hastes são classificadas em ordem crescente
  • Possui apenas caracteres numéricos (além do separador |)

Você não precisa lidar com números que possuem partes fracionárias. Você pode aprovar ou rejeitar zeros à esquerda extras nas hastes, mas uma haste em branco não é permitida. Haverá pelo menos um valor. Você só pode assumir espaços extras após as folhas em cada linha. Você pode assumir uma nova linha inicial e / ou posterior. Todos os caracteres serão imprimíveis em ASCII.

Sua função ou programa deve retornar ou gerar (para a tela ou a saída padrão) um valor verdadeiro para um gráfico válido ou um valor falso para um gráfico inválido. Você pode receber entradas da entrada padrão, de um arquivo, como uma string grande, como uma matriz de strings - o que for mais conveniente.

Aqui estão alguns casos de teste que são gráficos válidos (separados por linhas em branco):

2|00003457
3|35
4|799
5|3

99|3
100|0556
101|
102|
103|8

0|0

Aqui estão alguns casos de teste que são gráficos inválidos, com comentários à direita:

|0               Blank stem

5|347            Missing a stem (6) in the range
7|9

4|               Has a stem (4) outside the range
5|26
6|7

11|432           Leaves aren't sorted correctly
12|9989

5|357            Stems aren't sorted correctly
4|002
6|1

4|5              Duplicate stem
4|6
4|6
5|1

51114            No stem and leaf separator
609

1|2|03           Multiple separators
2|779|

4|8abcdefg9      Invalid characters
5|1,2,3

75 | 4 6         Invalid characters (spaces)
76 | 2 8 8 9

Isso é código de golfe, então o código mais curto vence! As brechas padrão não são permitidas.

Ben N
fonte
3
Este é um primeiro desafio muito bom, trabalho incrível! :) Eu adicionaria um caso de teste inválido que possui uma linha como 1|2|3esta.
Lynn
1
Excelente primeiro desafio!
AdmBorkBork 14/09/16
Bom primeiro desafio. Um caso de teste que você talvez possa adicionar é semelhante ao 4|;5|26;6|7que possui o primeiro tronco fora do intervalo, mas no final, ou seja 12|3;13|4559;14|.
Kevin Cruijssen 14/09/16

Respostas:

4

Perl, 47 bytes

Inclui +2 para -0p

Dê entrada no STDIN

stem.pl:

#!/usr/bin/perl -0p
$"="*";$_=/^((??{$_+$n++})\|@{[0..9,"
"]})+$/
Ton Hospel
fonte
Isso é incrível ... Esse truque $"é muito bom!
Dada
2

Pip , 60 58 + 1 = 59 bytes

Primeira facada no problema, provavelmente poderia usar mais golfe. Usa o -rsinalizador para ler as linhas de entrada do stdin. A saída verdadeira é 1, a saída falsa é 0ou uma sequência vazia.

g=a+,#g&a@vNE'|NEg@v@v&$&{Y(a^'|1)a@`^\d+\|\d*$`&SNy=^y}Mg

Explicação e suíte de testes pendentes, mas enquanto isso: Experimente online!

DLosc
fonte
1

JavaScript, 189 bytes

(x,y=x.split`
`.map(a=>a.split`|`),z=y.map(a=>a[0]))=>!(/[^0-9|\n]|^\|/m.exec(x)||/^\d+\|\n|\|$/.exec(x)||y.some((c,i,a)=>c.length!=2||c[1]!=[...c[1]].sort().join``)||z!=z.sort((a,b)=>a-b))

Solução alternativa com o mesmo comprimento:

(x,y=x.split`
`.map(a=>a.split`|`),z=y.map(a=>a[0]))=>!(/[^0-9|\n]|^\||^.*\|.*\|.*$/m.exec(x)||/^\d+\|\n|\|$/.exec(x)||y.some((c,i,a)=>c[1]!=[...c[1]].sort().join``)||z!=z.sort((a,b)=>a-b))

Define uma função anônima que recebe entrada como uma seqüência de linhas múltiplas.

Tenho certeza de que há mais para jogar golfe, então, deixe-me saber se você vê alguma melhoria possível.

Explicação:

A função verifica várias coisas ruins e, se alguma delas for verdadeira, ela retornará false (usando ORs lógicos e um NOT)

(x,y=x.split("\n").map(a=>a.split`|`),          //y is input in pairs of stem and leaves
z=y.map(a=>a[0]))                               //z is stems
=>                                              //defines function
!(                                              //logical not
/[^0-9|\n]|^\|/m.exec(x)                        //checks for invalid chars and blank stems
||/^\d+\|\n|\|$/.exec(x)                        //checks for stems out of range
||y.some((c,i,a)=>c.length!=2                   //checks for multiple |s in a line
||c[1]!=[...c[1]].sort().join``))               //checks if leaves are in wrong order
||z!=z.sort((a,b)=>a-b))                        //checks for stems in wrong order

Na solução alternativa, a verificação de vários |s em uma linha é feita como parte do primeiro regex.

DanTheMan
fonte
Se você usar em testvez de exec(você quase sempre deseja usar testse precisar apenas de um resultado booleano`), provavelmente poderá usar bit a bit ou em vez de lógico ou.
Neil
Isso realmente verifica se há hastes duplicadas ou ausentes?
Neil
Você poderia economizar alguns bytes substituindo y.some((c,i,a)=>...por y.some(c=>...uma vez ie anão são utilizados. E parece que z!=z.sort((a,b)=>a-b)não funciona pode ser substituído por''+z!=z.sort()
Hedi
1

Lote, 409 bytes

echo off
set/pp=||exit/b1
set t=
set i=%p:|=&set t=%
if "%t%"=="" exit/b1
for /f "delims=0123456789" %%s in ("%i%")do exit/b1
:l
set t=-
set s=%p:|=&set t=%
if "%s%"=="" exit/b1
if not "%s%"=="%i%" exit/b1
set/ai+=1
for /f "delims=0123456789" %%s in ("%t%")do exit/b1
:m
if "%t:~1,1%"=="" goto n
if %t:~0,1% gtr %t:~1,1% exit/b1
set t=%t:~1%
goto m
:n
set/pp=&&goto l
if "%t%"=="" exit/b1

Entra em STDIN, mas sai assim que vê um erro.

Neil
fonte