Validar un diagrama de tallo y hojas

20

Un diagrama de tallo y hoja muestra un grupo de valores numéricos en grupos, que están determinados por todos menos el último dígito. Por ejemplo, supongamos que tenemos este conjunto de datos:

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

Podríamos producir este diagrama de tallo y hoja:

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

El tallo de la primera fila es 0, por lo que sus "hojas", los dígitos después de la |, representan los valores entre 0 inclusive y 10 exclusivos. Las hojas de cada tallo están ordenadas. Los tallos sin hojas (como 3) todavía aparecen en la trama. El valor de 101 está entre 100 inclusivos y 110 exclusivos, por lo que su raíz es 10 (100 dividido por 10).

Su desafío es verificar si un texto es un diagrama válido de tallo y hoja. Una trama válida satisface estas reglas:

  • Tiene exactamente una fila para cada tallo (es decir, un grupo de 10) en el rango de los datos (incluidos los tallos en el medio del rango sin hojas)
  • No tiene tallos fuera del rango
  • Todas las hojas se ordenan ascendiendo a la derecha.
  • Todos los tallos están ordenados ascendiendo
  • Tiene solo caracteres numéricos (además del separador |)

No tiene que lidiar con números que tienen partes fraccionarias. Puede aprobar o rechazar ceros iniciales adicionales en los tallos, pero no se permite un tallo en blanco. Habrá al menos un valor. Solo puede asumir espacios adicionales después de las hojas en cada fila. Puede asumir una nueva línea inicial o final. Todos los personajes serán ASCII imprimibles.

Su función o programa debe devolver o generar (en la pantalla o la salida estándar) un valor verdadero para un gráfico válido, o un valor falso para un gráfico no válido. Puede tomar la entrada de la entrada estándar, de un archivo, como una gran cadena, como una matriz de cadenas, lo que sea más conveniente.

Aquí hay algunos casos de prueba que son gráficos válidos (separados por líneas en blanco):

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

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

0|0

Aquí hay algunos casos de prueba que son gráficos no válidos, con comentarios a la derecha:

|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

Este es el código de golf, por lo que gana el código más corto. Las lagunas estándar no están permitidas.

Ben N
fuente
3
Este es un primer desafío muy bonito, ¡trabajo increíble! :) Añadiría un caso de prueba no válido que tenga una línea como 1|2|3esta.
Lynn el
1
Excelente primer desafío!
AdmBorkBork
Bonito primer desafío. Un caso de prueba que quizás pueda agregar es similar al 4|;5|26;6|7que tiene el primer vástago fuera del rango, pero al final, es decir 12|3;13|4559;14|.
Kevin Cruijssen

Respuestas:

4

Perl, 47 bytes

Incluye +2 para -0p

Dar entrada sobre STDIN

stem.pl:

#!/usr/bin/perl -0p
$"="*";$_=/^((??{$_+$n++})\|@{[0..9,"
"]})+$/
Ton Hospel
fuente
Esto es increíble ... ¡Ese truco con él $"es muy bueno!
Dada
2

Pip , 60 58 + 1 = 59 bytes

Primero apuñale el problema, probablemente podría usar más golf. Utiliza la -rbandera para leer líneas de entrada de stdin. La salida de 1verdad es , la salida de falsa es 0o una cadena vacía.

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

Explicación y conjunto de pruebas pendientes, pero mientras tanto: ¡ Pruébelo en línea!

DLosc
fuente
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))

Solución alternativa de la misma longitud:

(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 una función anónima que toma la entrada como una cadena multilínea.

Estoy seguro de que hay más para el golf, así que avíseme si ve alguna mejora posible.

Explicación:

La función comprueba varias cosas malas y, si alguna de ellas es verdadera, devuelve falso (usando OR lógicos y un 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

En la solución alternativa, la comprobación de múltiples |s en una línea se realiza como parte de la primera expresión regular.

DanTheMan
fuente
Si usa en testlugar de exec(casi siempre quiere usar testsi solo necesita un resultado booleano '), entonces probablemente pueda usar bit a bit o en lugar de lógico o.
Neil
¿Esto realmente verifica si hay tallos duplicados o faltantes?
Neil
Usted podría ahorrar algunos bytes sustitución y.some((c,i,a)=>...por y.some(c=>...puesto iy ano se utilizan. Y parece z!=z.sort((a,b)=>a-b)que no funciona, podría ser reemplazado 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

Toma datos en STDIN, pero sale tan pronto como ve un error.

Neil
fuente