Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - dijsktra

#81
 Uff! El tema es muy denso para explicar en un sólo mensaje. Pero
vamos a intentarlo. Intenta, en un primer momento, olvidar que sabes
C/C++ o cualquier otro lenguaje.

 Sabes, desde los 10 años, que los enteros ( o los naturales,
racionales) son un tipo de números dotados de ciertas operaciones (la
suma, el producto...).  Allá por el último cuarto del siglo XIX, los
matemáticos europeos (Dedekind, Hilbert, Noether, Peano, Cantor y
otros... ) intentaban caracterizar las propiedades de esos "entes" y
sus operaciones. Te sonaran las propiedades commutativa, asociativa,
y algún valor especial como el elemento neutro,

sets
int
operations
+ : (int, int) -> int
constants
0 : int
axioms
a + b = b + a  [comm]
(a + b) + c = a + (b + c)  [assoc]
a + 0 = a  [e.neutro]
....


y los términos anillo, semigrupo, grupo conmutativo...

En computación, esos enteros y sus operaciones tienen una
representación trivial y limitada en el computador (int, con MAX_INT,
etc...)  que se proyecta en palabras de 8 o 16 bits y operaciones
básicas en la ALU...

Sin embargo, en algoritmia se necesitan además otros "tipos de
datos", como los que mencionas, (pila, cola, listas...) que también
se caracterizan por unas propiedades. Éstas también se pueden
expresar algebraicamente (aunque ya casi nadie lo practica, :-( )

En el caso de las pilas de enteros (stack), la estructura lineal más
sencilla, tenemos 3/4 operaciones.

Las operaciones, grosso modo, se dividen en tres grupos.
- constructoras
- modificadoras
- consultoras.


sets
stack, int, bool
constants
empty : stack
operations
push : (stack,int) -> stack
pop  : stack - -> stack
head : stack - -> int
isempty : stack -> bool
var
i : int
p : stack
axioms
pop(push(p,i))=p
head(push(p,i))=i
isempty(empty)=true
...


El primer axioma dice que al quitar (pop) un elmento de una pila (p)
a la que por lo menos se le ha añadido (push) un entero (i), nos
queda esa pila sin el elemento. Esto también lo sabes "por sentido
común", pero la novedad, repito, es la forma matemática, cuyo origen
debemos a los europeos del finales del s. XIX.


Y aquí entra el lenguaje C. Como no están implementadas a nivel
hardware, el lenguaje nos permite "simularlas" (ojo a la palabra, es
clave) con construcciones que tienen su base en elementos conocidos,
como arrays, punteros...


Los que programan la STL de C++ las ponen a tu disposición una serie
de estructuras (<stack>, <queue>, <list>) para que las uses en tus
algoritmos. Son de muy alta calidad y su implementación escapa a la
de cualquier principiante.

Pero podemos experimentar haciéndo las nuestras "de juguete".

- Para empezar, lo haremos con memoria estática, (arrays...)  

- En otro correo, si quieres, las podemos hacer con memoria dinámica
(punteros)

Observa que, al igual que con los int, al usar una array fijo de
elementos, la expresividad de nuestra implementación esta limitada a
un número maximo de elementos apilados.  

Al margen de esto, una operación no es aplicable siempre, como la
división por 0. Es el caso de la operación pop, o head. No son aplicables
sobre pilas vacías

En esos casos, su comportamiento está indefinido, por eso se emplea
la libreria <assert.h>.


#ifndef _STACK_TOY_
#define _STACK_TOY_
#define MAXIMUM 200

#include <assert.h>

typedef struct
{
 // I : 0 <= many <= MAXIMUM
 unsigned int many;
 unsigned int M[MAXIMUM];
} STACK, *PSTACK;

void empty( PSTACK pstack)
{
 pstack->many = 0 ;
}

void push(PSTACK pstack, const int i)
{
 assert((pstack->many)<MAXIMUM);
 pstack->M[pstack->many++]=i;
 return;
}

void pop(PSTACK pstack)
{
 assert((pstack->many)>0);
 pstack->many--;
 return;
}


int head(const PSTACK pstack)
{
 assert((pstack->many)>0);
 return pstack->M[pstack->many -1];
}

int isempty(const PSTACK pstack)
{
 return  (pstack->many == 0 );
}

 
#endif


#82
Perdón, tengo una objeción contra mis "objecciones".
En nuestra querida lengua, objeción es con una c. Y objección es un arcaísmo.
Mi latín me ha fallado (otras lenguas lo conservan, como el inglés, object, objection). Quien sabe... A lo mejor dentro de 500 años, los internautas vean que objeción y objeto, son arcaísmos, y mandan poner ojeto y ojeción, como ahora con sujeto y sujeción.


Cita de: dijsktra en  4 Abril 2018, 17:48 PM

Sin embargo, si tengo dos objecciones 'entre humanos' con este algoritmo:

Ya lo he cambiado allí.
#83
Cita de: NEBIRE en 22 Marzo 2018, 16:55 PM
Un palíndromo es una palabra que se 'lee' igual al derecho que al revés...

Luego, si yace en un array, básicamente se trata de comparar el primer 'carácter válido', con el último 'carácter válido', el segundo 'caracter válido', con el penultimo 'caracter válido' hasta llegar aunirse (que será o no el centor 'geométrico'.

Nota que la cuestión para no cometer errores, radica en: es 'carácter válido', lo mismo que en la descripción he marcado 'leer' entre comillas simples, para hacer notarlo...
De acuerdo. Una puntualización "pedantic" (perdón). Son los 'caracteres no válidos' los que delimitan las palabras dentro de una 'frase'

Cita de: NEBIRE en 22 Marzo 2018, 16:55 PM
Esto sería un sencillo algoritmo que recorre el array tomando caracteres válidos de ambos extremos y comparándolos:


buleano = funcion Espalindromo(array bytes B() )
   entero j,k, n

   j= b.length -1 // tamaño del array
   Hacer mientras (k<j)
       hacer mientras b(k) sea espacio   // buscar siguiente 'carácter válido'
           k +=1
       repetir
   
       hacer mientras b(j) sea espacio   // buscar anterior 'carácter válido'
           j -=1
       repetir

       Si b(k) es distinto de b(j) devolver false

       k +=1
       j -=1
   repetir

   devolver true
fin funcion


Nota que además de espacio, podría haber tabuladores, y otros signos de puntuación, como comas ',' '; ':', etc... si se da el caso, mejor crear una función que busque el siguiente carácter válido, rechanzando todos los no aceptables... para rechazar solo uno o dos, basta hacerlo 'in situ'.

Hay una errata (no un error) , por dejar la variable k sin inicializar, (k=0). Pero 'entre humanos', no entre compiladores, eso es una errata.

Sin embargo, si tengo dos objeciones 'entre humanos' con este algoritmo:


  • la primera, importante, de corrección,. supongamos la entrada de una frase de 420 espacios ... Entonces el primer bucle anidado progresa indefinidamente más allá de los límites permitidos...Lo que invalida el cómputo
  • La segunda, no tan importante, de complejidad temporal (en constante). Supongamos una frase de 420 caracteres, el primero y el ultimo distintos de espacio e iguales entre si, y el resto, entre medias espacios. Por ejemplo A....418 espacios...A.  Entonces, el algoritmo recorre cada casilla es recorrida 2 veces (420), cuando se puede hacer en una vez.  Repito, es una diferencia de constante, O(2n), vs O(n) en el caso peor. No es tan grave.


Aqui propongo, en primera instancia, el pseudocodigo que propongo

 Pseudocode:
 -----------

P:
 n,m=0,N
 while (n<m) and V[n]==' ')
   n=n+1
 while (n<m) and V[m-1]==' ')
   m = m - 1
I:
 while (m -n > 1 ) and (V[n]==V[m-1] )
    n=n+1
    while (n<m) and V[n]==' ')
      n=n+1
    m = m - 1
    while (n<m) and V[m-1]==' ')
      m = m - 1
 done
 Q:
 return (m-n)<=1


Notemos que en el caso peor, cada casilla se recorre exactamente una vez. Que no nos lie el anidamiento de bucles.... (Se puede hacer sin anidamientos también, pero NEBIRE empezó asi la buena idea...) ::) Quizás una forma "repeat until" sería de lectura más fácil,  pero lo dejo así, por ser la forma canónica de la derivación dijkstra...


init,
while b do
  restore
  step
done


Aquí va la implementación en C/C++, que aporto, puesto que estamos en la sección de C/C++.


Código (cpp) [Seleccionar]

#include <cstring> // strlen
#include <string>
#include <iostream>

using namespace std;

int palindrome(const char* W)
{
 int i,j;
 for(i=0,j=strlen(W); (i<j) && (W[i]==' ');i++);
 for( ; (i<j) && (W[j-1]==' ');j--);
 for( ; (j - i) > 1 && (W[i]==W[j-1]); )
   {
     for(i++; (i<j) && (W[i]==' ');i++);
     for(j--; (i< j) && (W[j-1]==' ');j--);
   }
 return ((j-i) <= 1 );
}



int main(int argc, char **args)
{
 string phrase;
 for (; getline(cin,phrase); )
   cout << palindrome(phrase.c_str()) << endl;
 return 0;
}


Estos son unos casos de prueba, donde 1 marca "true", y 0 "false". En el último caso, la linea solo contiene espacios, y como se ´lee igual' al derecho que al revés, da 1.

dabale arroz a la zorra el              abad
1
dabale arroz a                   la zorra el abad
1
dabale arroz al zorro el abad
0
                                                                                   
1



Y la guinda, (solo para aficionados al calculo Hoare y derivación Disjkstra). La justificación formal de su corrección.



 Palindrome on a given phrase, length(N) >= 0

 As a problem decission, we model it as an optimization problem

 P : W[N], N>= 0
 Q : 1 >= max i,j : 0 <=i <=j <= N and
                (j>i) ->
                ( V[i]!=' ' and V[j-1]!=' ' and
                  #k:0<=k<=i:V[k]!=' ' == #k:j<=k<=N:V[k-1]!=' ' and
                  V[i]!=V[j-1] )  
                  : j-i

i.e., the greatest segment not fullfilling palindrome conditions,
     1 or 0 if all of them fullfill.
     (see picture below)

                            (true)
                            15-16
                         ..........
             7----------------------------------24
         5----------------------------------------25
       4---------------------------------------------27
     3-------------------------------------------------28
   2-----------------------------------------------------29
 1---------------------------------------------------------30
0-------------------------------------------------------------31

0                                                               N=32
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|d|a|b|a|l|e| |a|r|r|o|z| |a| |l|a| |z|o|r|r|a| |e|l| |a|b|a|d| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


 (Long step strategy)

 B : (m-n) > 1 and V[n]==V[m-1]
 I :  0 <= n <= m <= N and
      (m-n> 1) -> (V[n]!=' ' and V[m-1]!=' ') and
      \forall i,j : 0 <= i < n and m<j<=N and
                    V[i]!=' ' and V[j-1]!=' ' and
    #k:0<=k<=i:V[k]!=' ' == #k:j<=k<=N:V[k-1]!=' '
                  :
                  V[i]==V[j-1] )
 
 C(m,n) = m -n >= 0
 Step: (At least decreases on 2, since B: m-n > 1 )
     n, m = n + (a-n), m-(m-b)
     where
        a = max i : n < i < m and AllessBl(V,n+1,i):i
        b = min i : a <= i < m and AllessBl(V,i,m-1):i


     
 O(n), despite the nested loops

Pseudocode
 -----------

P:
 n,m=0,N
 while (n<m-1) and V[n]==' ')
   n=n+1
 while (n<m) and V[m-1]==' ')
   m = m - 1
I:
 while (m -n > 1 ) and (V[n]==V[m-1] )
    n=n+1
    while (n<m-1) and V[n]==' ')
      n=n+1
    m = m - 1
    while (n<m) and V[m-1]==' ')
      m = m - 1
 done
 Q:
 return (m-n)<=1


 

#84
Programación C/C++ / Re: Funcion palíndromo.
22 Marzo 2018, 10:49 AM
Cita de: Spider-Net en 17 Septiembre 2008, 01:43 AM
Esto es una tontería pero bueno...


....
int Comprobar_frase (char frase[])
{
int longitud=strlen(frase);
int i=0;
while (i<=longitud/2 && frase[i]==frase[longitud-1-i])
 {
 i++;
 }
if (i>longitud/2)
  return 1;
  else
  return 0;
}
...


Quizás no sea tan tontería, amigo mío... :D  El

(i<=longitud/2)


hay que cambiarlo por


(i<longitud/2)


y el epílogo de la rutina

(i>longitud/2)

por

(i>=longitud/2)


EXPLICACION:
--------------
el programa es incorrecto si la palabra de entrada es vacía... ya que se accede a la posición [-1]. Y es claro que la palabra vacía es palíndromo.

"La palabra vacía no tiene ningún caracter. Por eso todos sus caracteres (es decir, ninguno, notese la paradoja) cumplen que son simétricos"

En lo de la forma de programar C, no me meto... Pero en general hay que usar con precaución el operador / de division entera...

Aquí teneis la solución que se pedía en pseudocódigo (luego lo hice en python)

https://foro.elhacker.net/ejercicios/necesito_ayuda_para_resolver_este_algoritmo-t481597.0.html;msg2157302#new
#85
Cita de: engel lex en 16 Marzo 2018, 18:50 PM
Entero i
Para i empezando en 0 y terminando en largo_palabra/2:
 Si palabra en i != palabra en largo_palabra - i:
   Imprimir no es palíndromo
   Terminar
 Fin Si
Fin Para

Imprimir palabra es palíndromo


Creo que la solución aportada está mal. Si empezamos a numerar las posiciones de una palabra en 0, como es normal en a mayoría de los lenguajes, W[0..N), con una palabra de longitud N=2, la expresión


palabra en largo_palabra - i:


compara los caracteres W[0] y  W[2-0], estando el segundo fuera de rango...

Es un problema sencillito, que todos hemos intentado siempre de memoria, pero del que se puede aprender mucho meditando...

Propongo dos ideas, las dos en complejidad O(n), aunque en términos absolutos, la segunda es el doble de rápida que la primera...

Primera, sin tener en cuenta la propia simetría del problema, en un bucle de N veces...
Es un problema de decisión y se trata de devolver el menor indice n que no cumpla la condición de palíndromo con su homólogo N-n-1 o en su defecto, N, si todos lo cumplen. Formalmente



P : N >= 0
Q : N==min i: 0<=i and (N=i or V[i]!=V[N-i-1]):i

0     1    n=2               N-2   N-1   N
+-----+-----+-----+-...-+-----+-----+-----+
|  A  |  B  |     |     |     |  B  |  A  |
+-----+-----+-----+-...-+-----+-----+-----+

I : \forall i : 0 <= i < n : V[i] == V[N-i-1]
     and
     0 <= n <= N
B :  (n < N) and (V[n]==V[N-n-1])
init : n = 0
Restore: skip
C(N,n) : N-n >= 0
Step : n = n + 1  
O(n)


Y este es el código

Pseudocode
------------
n=0
while n<N and V[n]==V[N-n-1]
  n = n +1
done
return n==N


Como habréis notado, una vez se pasa de la mitad, resulta innecesario seguir procesando.
Esa es la idea que quiso desarrollar engel lex. De trivial no tiene nada.

Se trata de buscar el intervalo de longitud máxima menor que N y de la forma [i..N-i) tal que sus extremos i e N-i-1 no cumplan la condición de palindromo, o el intervalo vacío o de un elemento si todos lo cumplen. Si este intervalo es menor o igual que 1, la palabra es palindromo. La idea formal, ilustrada con un dibujo, puede ser esta


                     i  N-i
                     ....
                  3         N-3
                  ------------
            2                      N-2
            ------------------------
      1                                  N-1
      ------------------------------------
0                                               N
-------------------------------------------------
0     1     2     3          N-3   N-2   N-1    N
+-----+-----+-----+-...-+-...-+-----+-----+-----+
|  A  |  B  |  C  |     |     |  C  |  B  |  A  |
+-----+-----+-----+-...-+-...-+-----+-----+-----+



  Key : Think on [i..N-i) intevals and distances: (N-i)-i
 
P : N >= 0
Q : 0=max i:(N>=(N-i)-i)and ((N-i)-i=0 or V[i]!=V[N-i-1]):N-i-i

I : N>=N-n-n>=0 and
     \forall i : N>= N-i-i > (N-n-n) : V[i]=V[N-i-1]

B  : N-n-n > 1 and V[n]==V[N-n-1]   
init n=0
Restore: skip
C(N,n) : N-n-n >= 0
Step : n = n + 1  (decreases on two!)

y este es el código. Como vemos, no inspecciona todas las casillas dos veces, como el anterior. Notablemente es más difícil, claro, aunque igual de complejidad temporal O(n)


Pseudocode
------------
n=0
while (((N-n)-n) > 1) and V[i]==V[N-i-1]
   n = n +1
done
return (((N-n)-n) <= 1)


Notese que la expresión

(((N-n)-n) > 1)

es equivalente, -en este caso- a la que persguía engel lex,

n<N/2

pero nosotros, tardando un poco más hemos llegado a ella razonadamente, completando la intuición que todos hemos tenido de siempre de este algoritmo y que, como es el caso, podría llevarnos a errores.

Me he permitido pasarlo a python, para tener alguna "experiencia real"  del algoritmo.

def palyndrome(V):
    n = 0
    while ((len(V)-n)-n > 1) and V[n]==V[-n-1]:
        n+=1
    return ((len(V)-n)-n <= 1)




Con estos resultados.

>>> palyndrome("abccba")
True
>>> palyndrome("abcba")
True
>>> palyndrome("abcca")
False
>>> palyndrome("aaabbb")
False
>>> palyndrome("aaabbbaa")
False
>>> palyndrome("aaabbbaaa")
True
>>> palyndrome("123454321")
True
>>> palyndrome("123454322")
False
>>> palyndrome("")
True
>>> palyndrome("1")
True
>>> palyndrome("12")
False
>>> palyndrome("11")
True
#86
Es muy fácil. Aquí va esta solución, que pide en primer lugar el número de notas y después las notas.

Consejo: Pon el "asunto" algo más significativo de lo que quieres resolver para poder saber que buscas. Todos son ejercicios, todos necesitamos ayuda... Por ejemplo, en tu caso , sería una buena idea para distinguirlo del resto.

Asunto: media aritmética


Y el código:
Código (cpp) [Seleccionar]

#include <iostream>

using namespace std;

/*
   P : N > 0
   Q : sum = \sum i : 0 <= i < N : V[i]
       less = #i : 0 <= i < N : N*V[i] < sum
       greater = #i : 0 <= i < N : N*V[i] > sum
*/
void statistics(const int V[], const int N, int &sum, int &less, int &greater)
{
  int n;
  for (n=sum=0;n<N;n++) sum+=V[n];
  for (n=less=greater=0;n<N;n++)
    {
      less+=((N*V[n]) < sum) ;
      greater+=((N*V[n]) > sum) ;
    }
  return ;
}

#define MAX 1000

int main()
{
  int V[MAX];
  int N, sum, less,greater;
  cin >> N ;
  for (int n=0; n < N ; n++)  cin >> V[n];
  statistics(V,N,sum,less,greater);
  cout << ((float)sum/N) << "  " << less << "  " << greater << endl;
  return 0 ;
}


Algunos ejemplos:

Dos notas, valores 1 y 2 ...

2
1 2


La media es 0.5 y hay 1 menor (el 1) y 1 mayor (el 2)

1.5  1  1


Tres valores.

3
1 0 0


La media es 0.333333 (cuidado!, los "float" no son precisos!, es 0.3333333333333... infinitas veces)  y hay 2 menores (los 0) y 1 mayor (el 1)

0.333333  2  1



(Te dejo que interpretes tú este)

3
2 2 2


(salida)
2  0  0
#87
Ejercicios / Particion aritmetica en python
11 Marzo 2018, 00:47 AM
Vuelvo a recuperar la cuestión no resuelta desde Mayo del 2017

https://foro.elhacker.net/ejercicios/ejercicio_bucle_while_en_python-t469250.0.html

"Dados dos números enteros n (n≥0) y a (a>0) encontrar, si existe, el
menor entero x del intervalo [0, n] para el que se cumpla lo siguiente: la diferencia
entre las sumas de los valores enteros de los intervalos [n-x, n] y [0, x] coincide
con a."

Se mostraron dos soluciones:

La primera es incorrecta, ya que para n = 100000 y para a= 350 se daba x=449, cosa que no
es cierta, pues

>>> n,a,x = 100000, 350, 449
>>> n,a,x
(100000, 350, 449)
>>> a == sum(range(x,n+1)) - sum(range(0,x+1))
False
>>> a ,  sum(range(x,n+1)) - sum(range(0,x+1))
(350, 4999848399)


En la segunda, se dice que el problema se puede resolver en O(1) sin más que resolver la ecuacion
(n-x)x+(n-x)=a
diciendo que (n-x)x+(n-x)  es la diferencia buscada. Cosa que no es, ya que

>>> n,x
(100000, 449)
>>> (n-x)*x+(n-x) ==  sum(range(x,n+1)) - sum(range(0,x+1))
False
>>> (n-x)*x+(n-x) , sum(range(x,n+1)) - sum(range(0,x+1))
(44797950, 4999848399)


Propongo mi solución. La ecuación que hay que resolver en valores enteros 0 <= x <=n es (al final del mensaje digo como la he obtenido):

n(n+1) = 2(a+x^2)

En el cuerpo de los complejos, siempre tiene solución, pero en los enteros 0 <= x <= n puede que ésta no exista, por lo que emplearé el tipo None de Python para expresar esta circunstancia...


El algoritmo python que lo resuelve es el siguiente:

Código (python) [Seleccionar]
'''
   P :  N >= 0 and a > 0
   Q : x = min i : 0 <= i <= N and N(N+1)==2(a +i^2) : i
'''
def partition(N,a):
    m = 0
    while (m<=N) and (N*(N+1)!=2*(a+m*m)):
        m=m+1
    return (None if m>N else m)




Van algunos ejemplos


>>> for n in range(5,10):    
       for a in range(6,10):
           print n,a , " => Sol : " , partition(n,a)



Lo que arroja esta salida

5 6  => Sol :  3
5 7  => Sol :  None
5 8  => Sol :  None
...
9 7  => Sol :  None
9 8  => Sol :  None
9 9  => Sol :  6



Vemos que


>>> n,a,x = 5,6,3
>>> n,a,x
(5, 6, 3)
>>> a == sum(range(x,n+1)) - sum(range(0,x+1))
True
>>> a , sum(range(x,n+1)) - sum(range(0,x+1))
(6, 6)


El caso n=100000 y a = 350, no tiene solución.

Si puedo, mañana escribo de donde sale la ecuación.
#88
Un problema bonito y "raro"...
Ahí va un programa que vale para cualquiera N carcateres, (hasta 1000), metidos por teclado, hasta que se mete el fin de fichero... (no incluye separadores entre los caracteres)


#include <iostream>
#include <algorithm> // min, max

using namespace std;

#define MAX 1000

/*


 P : N >= 0
 Q : count = #i : 0 <= i < N-1: twin(V,N,i)

 where twin(V,N,i) ::= V[i]==V[i+1]) &&
                       ((i==0) ||
                       ((i>0) and V[i]!=V[i-1]) ||
                       (i>1) and V[i-1]==V[i-2])

*/
int twins(const int V[MAX], const int N)
{
 int n,count;
 for(n=count=0; n<N-1 ; n+=1+(V[n]==V[n+1]))
   count += (V[n]==V[n+1]) ;
 return count;
}

int main(int argc, char *args[])
{
 char c;
 int N;
 int V[MAX];
 for ( N=0  ; (N<MAX) && (cin >> c) ; N++ )  V[N]= c;
 cout << N << " " << twins(V,N) << endl;
 return 0;
}

/*

0           n                             N
+-----+-----+-----+-----+-----+-...-+-----+
|  a  |  a  |  a  |  b  |  b  |     |  r  |
+-----+-----+-----+-----+-----+-...-+-----+

(Bizarre...)

 I : Q[N/n] and
     0 <= n <= N
     
 B : n<N-1
 C(n) : N-n >= 0
 step : n = n + (1 + V[i]==V[i+1])
 O(n) (linear)

*/





a

El primer parametro da el numero de caracteres leidos (N) el segundo, el numero de "parejas" según el criterio del problema

1 0

aaa

3 1

aaaaa

5 2

aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooo*

46 15

(La linea tiene 46 caracteres y 15 parejas)

Y la bonita. Es importante el * porque cin no toma separadores y saldrian más parejas de las normales, juntando los renglones.

aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooo*
oooaaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnn*
nnnoooaaabbbcccdddeeefffggghhhiiijjjkkklllmmm*
mmmnnnoooaaabbbcccdddeeefffggghhhiiijjjkkklll*
lllmmmnnnoooaaabbbcccdddeeefffggghhhiiijjjkkk*
kkklllmmmnnnoooaaabbbcccdddeeefffggghhhiiijjj*
jjjkkklllmmmnnnoooaaabbbcccdddeeefffggghhhiii*
iiijjjkkklllmmmnnnoooaaabbbcccdddeeefffggghhh*
hhhiiijjjkkklllmmmnnnoooaaabbbcccdddeeefffggg*
ggghhhiiijjjkkklllmmmnnnoooaaabbbcccdddeeefff*
fffggghhhiiijjjkkklllmmmnnnoooaaabbbcccdddeee*
eeefffggghhhiiijjjkkklllmmmnnnoooaaabbbcccddd*
dddeeefffggghhhiiijjjkkklllmmmnnnoooaaabbbccc*
cccdddeeefffggghhhiiijjjkkklllmmmnnnoooaaabbb*
bbbcccdddeeefffggghhhiiijjjkkklllmmmnnnoooaaa*


15 lineas por 15 parejas da 225 parejas


690 225


#89
Primero va una muestra del cálculo del trangulo de Pascal de base N=10

10

    1     1     1     1     1     1     1     1     1     1
    1     2     3     4     5     6     7     8     9
    1     3     6    10    15    21    28    36
    1     4    10    20    35    56    84
    1     5    15    35    70   126
    1     6    21    56   126
    1     7    28    84
    1     8    36
    1     9
    1


Y ahora uno de N=20. Quizás puedas no apreciarla dependiendo de la distorsión que pueda ocasionar la resolución de carcateres.

20
    1     1     1     1     1     1     1     1     1     1     1     1     1     1     1     1     1     1     1     1
    1     2     3     4     5     6     7     8     9    10    11    12    13    14    15    16    17    18    19
    1     3     6    10    15    21    28    36    45    55    66    78    91   105   120   136   153   171
    1     4    10    20    35    56    84   120   165   220   286   364   455   560   680   816   969
    1     5    15    35    70   126   210   330   495   715  1001  1365  1820  2380  3060  3876
    1     6    21    56   126   252   462   792  1287  2002  3003  4368  6188  8568 11628
    1     7    28    84   210   462   924  1716  3003  5005  8008 12376 18564 27132
    1     8    36   120   330   792  1716  3432  6435 11440 19448 31824 50388
    1     9    45   165   495  1287  3003  6435 12870 24310 43758 75582
    1    10    55   220   715  2002  5005 11440 24310 48620 92378
    1    11    66   286  1001  3003  8008 19448 43758 92378
    1    12    78   364  1365  4368 12376 31824 75582
    1    13    91   455  1820  6188 18564 50388
    1    14   105   560  2380  8568 27132
    1    15   120   680  3060 11628
    1    16   136   816  3876
    1    17   153   969
    1    18   171
    1    19
    1


Puedes computar tritangulos de base hasta N=30, pero a no ser que tengas una resolucion suficiente en el terminal de caracteres por pantalla, las figuras saldran sin formatear, y el efecto del trangulo se puede perder... Cuidado también con N altos porque los enteros se pueden salir de rango y acabar en negativos... usar unsigned long....


Y este es el código que lo resuelve... Ah!, empecé a hacerlo en C++, pero con pocos cambios puedes pasarlo a C.

#include <iostream>  // cin, cout
#include <iomanip>  // setw

using namespace std;

#define MAX 1000

// P : N > 0
// Q : \forall ii,jj : 0 <= ii,jj < N : M[ii][jj]=C(ii+1,jj+1)
// I : i > 0 -> \forall jj : 0 <= jj < N : M[i-1][jj]=C(i-1,jj)

// Inner loop
// I2 : \forall jj : 0 <= jj < j : M[i][jj]=C(i+1,jj+1)
// and
// acum = i>0 -> acum= \sum k:0<=k<j: M(i-1,k)

// where C(i,j) is combinatory number
//  C(1,j) = 1
//  C(i+1,j) = \sum k:1<=k<=j: C(i,k)

void pascal(int M[][MAX], const int N)
{
 int acum;
 int i,j;
 for ( i=0; i<N ; i++)
   for ( j=acum=0; j< N-i ; j++)
     if (i==0)
M[i][j]= 1;
     else
{
 acum += M[i-1][j];
 M[i][j] = acum;
}
 return;
}

int main(int argc, char **args)
{
 int N;
 int M[MAX][MAX];
 cin >> N ;
 pascal(M,N);
 for (int i=0; i < N ; i++)
   {
     for (int j=0; j < N-i ; j++)
cout << setw(5) << M[i][j] << " " ;
     cout << endl;
   }
 return 0;
}

#90
A ver, no se si tiene mucho interes quitar los espacios del principio del fichero, pero yo contribuyo a resolver la ultima parte del mensaje

Cita de: ByFuenteS en 14 Febrero 2018, 10:48 AM
[...]
Alguien me podria ayudar con este codigo y a poder ser también con la busqueda de una palabra que aparece varias veces en mi código y necesito indicar la linea y la posicion en la que aparece. Muchas gracias!!!

Primero el ejemplo de ejecución: buscar "en el código" (o cualquier fichero de texto en general) las apariciones de una palabra "perror" (o cualquier palabra) indicando linea y columna.

Entrada

searchWord.c perror

(Creo que la segunda falla, porque el editor emacs que uso mete \t para dar formato al texto C...pero ya no sigo a corregirlo.)

Salida

45:6 perror
53:3 perror
80:6 perror


Y ahora el código... Se trata del algoritmo más trivial de este estilo, con una complejidad theta(N*M), siendo N el numero de caracteres del archivo y M la longitud (mayor que 0) del patron a buscar. (Está claro que los google engines nunca utilizarán este algoritmo  ;D)



/*
 Naive string matching on file .
 Theta(N*M) ,
 N (length of contents)
 M (length of pattern)
*/

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <assert.h>

#include <string.h>


/*

I : lineno = #i : 0 <= i <= n : V[i]='\n'
    column = max p : 0<= p <= n and AllesNotRet(V,p,n)   : n-p
    buf[0..min(n,m))=V[max(n-m,0),n)

 Invariant snapshot

0                                        n=7
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|  a  |  b  |  c  | \n  |  s  |  e  |  r  |  a  |     |     |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+

             buf= "\nser"
     lineno=1
     colum=3
     pattern=sera
     m = 4
*/


// IO
void searchPattern(FILE *f, const char pattern[])
{
 int n,lineno,column;
 const int m = strlen(pattern);
 char *buf ;
 if (!(buf=(char *)calloc(m,sizeof(char))))
   {
     perror("calloc");
     exit(EXIT_FAILURE);
   }
 for(lineno=column=n=0 ; !feof(f) ; n++)
   {
     char chr=fgetc(f);
     if (ferror(f))
{
 perror("fgetc");
 exit(EXIT_FAILURE);
}
     int i;
     for(i=0; i<m-1 ; i++) buf[i]=buf[i+1]; // shift window
     buf[m-1]=chr;
     if (strncmp(buf,pattern,m)==0)
printf("%d:%d\t%s\n",lineno+1,column-m+1,pattern);
     lineno += (chr=='\n');
     column =  (chr =='\n')?0:(column+1);
   }
 free(buf);
 return;
}


int main (void)
{
 FILE *f;
 int n,N;

#define MAX 10000
 char path[MAX];
 char word[MAX];
 scanf("%s %s",path,word);
 if (!(f = fopen(path,"r")))
   {
     perror("fopen");
     exit(EXIT_FAILURE);
   };
 searchPattern(f,word);
 fclose(f);
 return 0;
}

/*
Note : Formal Specification is done referring to V[0..N)/(POS[0..P))
      instead of file stream (f)/(stdin)
     
P : M > 0
Q : P = #i : 0 <= i < N : buf[0..m)=V[i,min(i+m,N))
   \forall i : 0 <= i < P : V[POS[i]..POS[i]+m)=pattern[0..m)
                            V[POS[i]-COLUMN[i]-1]=\n and
                            LINE[i]=#i : 0 <= i < POS[i] : V[i]=\n
*/