procedimientos - Imprimir una pirámide de alfabeto en PL/SQL
procedimientos oracle sql developer (5)
Tengo un ejercicio para escribir un programa que imprime una pirámide de alfabeto como esta:
A
ABA
ABCBA
ABCDCBA
ABCDFDCBA
La tarea también sugiere usar INSTR, LPAD, UPPER.
Quiero tener la pirámide que contiene todas las letras del alfabeto. Sin embargo, creo que es más fácil hacerlo primero en números así que:
IF x in 0..25 loop
dbms_output.put_line(x);
end loop;
end;
El resultado es solo una línea recta de números del 0 al 25. No sé cómo agregar espacios antes de los números, que finalmente deben ser letras, para formar una forma de pirámide. Por favor, no den la respuesta completa, solo necesito algunas sugerencias y direcciones para resolver esta tarea.
Dos sugerencias:
En la primera línea hay 1 letra, en la segunda línea 3 letras, en la tercera línea 5 letras ... así que 1, 3, 5, 7, 9 ... hasta el infinito. No puedo entender lo que quieres con:
IF x in 0..25 loop
El carácter de la línea de corte para su dbms_output es:
chr(13)||chr(10) -> Windows
chr(10) -> Unix
Este funciona:
DECLARE
aLine VARCHAR2(100);
BEGIN
FOR PyramidLevel IN 0..25 LOOP
aLine := NULL;
FOR i IN 0..PyramidLevel-1 LOOP
aLine := aLine || CHR(i+65);
END LOOP;
FOR i IN REVERSE 0..PyramidLevel LOOP
aLine := aLine || CHR(i+65);
END LOOP;
aLine := LPAD(aLine, 26+PyramidLevel);
DBMS_OUTPUT.PUT_LINE(''_''||aLine);
END LOOP;
END;
_ A
_ ABA
_ ABCBA
_ ABCDCBA
_ ABCDEDCBA
_ ABCDEFEDCBA
_ ABCDEFGFEDCBA
_ ABCDEFGHGFEDCBA
_ ABCDEFGHIHGFEDCBA
_ ABCDEFGHIJIHGFEDCBA
_ ABCDEFGHIJKJIHGFEDCBA
_ ABCDEFGHIJKLKJIHGFEDCBA
_ ABCDEFGHIJKLMLKJIHGFEDCBA
_ ABCDEFGHIJKLMNMLKJIHGFEDCBA
_ ABCDEFGHIJKLMNONMLKJIHGFEDCBA
_ ABCDEFGHIJKLMNOPONMLKJIHGFEDCBA
_ ABCDEFGHIJKLMNOPQPONMLKJIHGFEDCBA
_ ABCDEFGHIJKLMNOPQRQPONMLKJIHGFEDCBA
_ ABCDEFGHIJKLMNOPQRSRQPONMLKJIHGFEDCBA
_ ABCDEFGHIJKLMNOPQRSTSRQPONMLKJIHGFEDCBA
_ ABCDEFGHIJKLMNOPQRSTUTSRQPONMLKJIHGFEDCBA
_ ABCDEFGHIJKLMNOPQRSTUVUTSRQPONMLKJIHGFEDCBA
_ ABCDEFGHIJKLMNOPQRSTUVWVUTSRQPONMLKJIHGFEDCBA
_ ABCDEFGHIJKLMNOPQRSTUVWXWVUTSRQPONMLKJIHGFEDCBA
_ ABCDEFGHIJKLMNOPQRSTUVWXYXWVUTSRQPONMLKJIHGFEDCBA
_ABCDEFGHIJKLMNOPQRSTUVWXYZYXWVUTSRQPONMLKJIHGFEDCBA
Parece que DBMS_OUTPUT.PUT_LINE()
recorta los caracteres espaciales principales (al menos en mi TOAD), así que puse _
al principio.
Una forma de hacerlo es generar la base de la pirámide:
-
CHR(n)
generará un carácter ASCII; y - puedes concatenar cadenas con
||
así questr := str || CHR(65)
str := str || CHR(65)
agregará unaA
al final de la cadena. - La instrucción
FOR i IN [REVERSE] 1 .. repetitions LOOP
se puede usar para recorrer valores.
Si puede generar la base, entonces la función TRANSLATE
puede reemplazar a varios caracteres con otros caracteres en una correspondencia de 1 a 1, de modo que:
-
TRANSLATE( ''ABC'', ''ABC'', '' A'' )
saca'' A''
-
TRANSLATE( ''ABC'', ''ABC'', '' AB'' )
saca'' AB''
-
TRANSLATE( ''ABC'', ''ABC'', ''ABC'' )
saca''ABC''
Si ha generado la base de la pirámide, entonces tiene una cadena donde la subcadena comienza con esos caracteres y solo necesita subcadena de la longitud adecuada rellenada con espacios.
DBMS_OUTPUT.PUT_LINE( string )
imprimirá una cadena a la consola.
Solución completa: NO SIGA EL ENLACE SI NO QUIERE SABER CÓMO HICE ESTO
Puro SQL usando la cláusula modelo
select lpad(x1, 26, '' '') || substr(x2, 2) x from dual
model
dimension by (1 id)
measures (cast(null as varchar2(26)) x1, cast(null as varchar2(26)) x2)
(x1[for id from 1 to 26 increment 1] = x1[cv(id)-1] || chr(64+cv(id)),
x2[for id from 1 to 26 increment 1] = chr(64+cv(id)) || x2[cv(id)-1]);
X
---------------------------------------------------
A
ABA
ABCBA
ABCDCBA
ABCDEDCBA
ABCDEFEDCBA
ABCDEFGFEDCBA
ABCDEFGHGFEDCBA
ABCDEFGHIHGFEDCBA
ABCDEFGHIJIHGFEDCBA
ABCDEFGHIJKJIHGFEDCBA
ABCDEFGHIJKLKJIHGFEDCBA
ABCDEFGHIJKLMLKJIHGFEDCBA
ABCDEFGHIJKLMNMLKJIHGFEDCBA
ABCDEFGHIJKLMNONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTUTSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTUVUTSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTUVWVUTSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTUVWXWVUTSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTUVWXYXWVUTSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTUVWXYZYXWVUTSRQPONMLKJIHGFEDCBA
26 rows selected.
Actualizar. Solo por diversión, el mismo resultado con una sola regla
select lpad('' '', 26 - ceil(length(x)/2), '' '') || x as x from dual
model
dimension by (1 id)
measures (cast(null as varchar2(51)) x)
(x[for id from 1 to 26 increment 1] = substr(x[cv(id)-1], 1, cv(id)-1) || chr(64+cv(id)) || substr(x[cv(id)-1], cv(id)-1));
select lpad('' '', 26 - ceil(length(x)/2), '' '') || x as x
from (select ''A'' x from dual union all select ''ABA'' from dual)
model
dimension by (rownum id)
measures (cast(x as varchar2(51)) x)
(x[for id from 3 to 26 increment 1] = regexp_replace(x[cv(id)-1], ''(.)(.)/1'', ''/1/2'' || chr(64+cv(id)) || ''/2/1''));
Puedes hacerlo todo en SQL. Esto funciona en Toad (se ejecuta como un script; F5). Nota Obtuve un error de "número inválido" a menos que complete el "nivel-1" en una llamada TO_NUMBER () en la segunda llamada a regexp_substr.
Sugerencias: utilice el constructo CONNECT BY para recorrer las filas. CONNECT BY pone a disposición automáticamente una variable llamada level
que se incrementa para cada iteración.
Busca patrones. ¿Cuántas filas se esperan? ¿Cuántos espacios hay delante de la primera letra para cada fila? ¿Qué variables están disponibles que puede manipular en un cálculo? Otras respuestas proporcionan pistas también.
¿Notaste la secuencia de Fibonacci? El número de caracteres en cada fila es la suma de ese número de fila más el número de la fila anterior (nada que ver con la respuesta (al menos mi respuesta), solo un patrón que noté).
El ejemplo del violín de SQL responde aquí, pero los espacios iniciales no se mostrarán. Tienes que pegar la solución en Toad o SQLPlus y descomentar las líneas "establecer".
Editar: Fui a SQL Fiddle para probar algo y encontré que estaba colgando. Como no quería que mi respuesta se perdiera y todos publicaban respuestas completas de todos modos, aquí está para la posteridad:
SQL> set heading off;
SQL> set feedback off;
SQL> set pagesize 0;
SQL>
SQL> select lpad('' '', 26-level, '' '') ||
regexp_substr(''ABCDEFGHIJKLMNOPQRSTUVWXYZ'', ''(.{'' || level ||''})'', 1, 1, NULL, 1) ||
reverse(regexp_substr(''ABCDEFGHIJKLMNOPQRSTUVWXYZ'', ''(.{'' || to_number(level-1) ||''})'', 1, 1, NULL, 1)) pyramid
from dual
connect by level <= 26;
A
ABA
ABCBA
ABCDCBA
ABCDEDCBA
ABCDEFEDCBA
ABCDEFGFEDCBA
ABCDEFGHGFEDCBA
ABCDEFGHIHGFEDCBA
ABCDEFGHIJIHGFEDCBA
ABCDEFGHIJKJIHGFEDCBA
ABCDEFGHIJKLKJIHGFEDCBA
ABCDEFGHIJKLMLKJIHGFEDCBA
ABCDEFGHIJKLMNMLKJIHGFEDCBA
ABCDEFGHIJKLMNONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTUTSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTUVUTSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTUVWVUTSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTUVWXWVUTSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTUVWXYXWVUTSRQPONMLKJIHGFEDCBA
ABCDEFGHIJKLMNOPQRSTUVWXYZYXWVUTSRQPONMLKJIHGFEDCBA
SQL>