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

#71
Hola Sonia.

No he tenido mucho tiempo, porque me voy a ver el partido del mundial de España-Irán   :xD :D.

Echa un vistazo a esto... (No he probado, mañana edito una respuesta más elaborada, e implemento el programa principal, aunque no lo pide)



#define MAX 10000
#include <assert.h>

/* Static memory implementation */

typedef struct {
  int V[MAX];
  int N;
} CycleSeq, *pCycleSeq;


/* Comment: Compare cannonical forms */
int SameCycle(CycleSeq *A, CycleSeq *B)
{

  if (A->N != B->N) return 0;

  if (A->N == 0 ) return 1 ;

  // otherwise
  assert((A->N == B->N) && A->N );

  int n ;
  int mA, mB;
  for (mA=mB=0, n = 1 ; n < A->N ; n++)
    {
      if (A->V[mA]>A->V[n]) mA = n ;
      if (B->V[mB]>B->V[n]) mB = n ;
    };
  // mA mB holds minimum positions;
// count coincidences in cannonical form.
  int count;
  for(count=0; (count < A->N) && (A->V[mA]==B->V[mB]); mA=(mA+1)% A->N,mB=(mB+1)%A->N  )
    count++;
  return count == A->N;
}
#72
Cita de: NEBIRE en 13 Junio 2018, 20:05 PM
Quizás no le parezca solucionado, porque no obedece a lo que él espera, y en tal caso, lo que falla es su especificación de pareja.[...]

Según el planteamiento, exige soluciones distintas. Qué especifique con claridad la consideración de pareja... puede que así tenga solucionado su problema o aún no.

Exacto!,  ;-)  esa es la cuestión. Especificar sin ambigüedad. Por eso yo intento siempre dar una especificación formal, sin ambigüedades. Mi propuesta era:

/*


  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])

*/


"Ahí" dice que un caracter es adyacente (twin no es la palabra mejor, en fin...) al siguiente  V[n]==V[n+1]) si no está atado ya inmediatamente anterior V[n]!=V[n-1]. Es posible que no esté atado (aun siendo igual) si ya el anterior estaba atada al anterior del anterior...El razonamiento se aplica a cualquiera, menos al primero (n == 0)  que no tiene anterior"

Uno puede estar de acuerdo con ella o no, (las definiciones se proponen, pero no se demuestran) pero si se escoje, el programa dado en

https://foro.elhacker.net/programacion_cc/buenos_diastengo_muchas_dudas_con_un_ejercicio_de_caracteres-t480917.0.html;msg2155561#msg2155561


cumple lo que se le pide.
#73
Programación C/C++ / Re: [Función fscanf]
20 Junio 2018, 15:42 PM
Cita de: dijsktra en 23 Abril 2018, 01:14 AM
Una solución pasa por dejar usar las rutinas "high-level IO", los streams, a las de "low-level IO", los "file descriptors".

El incoveniente es que perdemos la funcionalidad de la rutina

long ftell(FILE *stream)


Esto no es así necesariamente. Me corrijo a mí mismo. En high-level contamos con

int fgetc(FILE *stream);


que, sin buscar patrones como scanf, hace lo que queremos, conservando el ftell
El erroes es que en vez de scanf , la rutina qie había que haber utilizado era
fgetc

El nuevo programa, más sencillo queda:


#include <stdlib.h> // exit()...
#include <assert.h> // assert
#include <stdio.h> //p printf
#include <ctype.h> // isprint

int main()
{
  char c;
  int n;
  FILE* fs;
  const char *pattern="%d\t%c\t%d\n";
  char row[80];
  if (!(fs=fopen("texto.txt","r")))
    {
      perror("fopen");
      exit(EXIT_FAILURE);
    }
  printf("ASCII\tPrint\tPos\n");
  while((c=fgetc(fs))!=EOF)
    {
      assert(isascii(c));
      if ((n=sprintf(row,pattern,c,isprint(c)?c:' ',ftell(fs)))<0)
{
  perror("sprintf");
  exit(EXIT_FAILURE);
}
      printf(row);
    }
  if (c!=EOF)
    {
      perror("fgetc");
      exit(EXIT_FAILURE);
    }
  fclose(fs);
  exit(EXIT_SUCCESS);
}


Y la salida, como en el caso anterior, leyendo "texto.txt", queda


ASCII Print Pos
115 s 1
117 u 2
112 p 3
104 h 4
111 o 5
108 l 6
97 a 7
115 s 8
97 a 9
100 d 10
107 k 11
106 j 12
104 h 13
111 o 14
108 l 15
97 a 16
115 s 17
97 a 18
100 d 19
10 20
97 a 21
100 d 22
104 h 23
111 o 24
108 l 25
97 a 26
100 d 27
115 s 28
97 a 29
10 30

#74
A ver, gusanillo, este problema ya lo preguntaste aquí ( y creo que resuelto)

https://foro.elhacker.net/programacion_cc/buenos_diastengo_muchas_dudas_con_un_ejercicio_de_caracteres-t480917.0.html;msg2155561#msg2155561

Si ponemos "caracteres adyacentes por parejas" o algo similar en el tema, podremos localizarlo mejor
#75
hola!

Yo preferiría hacerlo sin invertir las cadenas, porque es más fácil, pero si hay que hacerlo invirtiendo....


1 version. Sin incluir espacios, sólo palabras



#include <string> // string
#include <iostream>  // cin, cout
#include <cstdlib> //  malloc
   
using namespace std;

int palindrome(const char* W)
{
  char *jj;
  const char *i, *j;
  for(i=W  ; *i  ;i++) ;  // compute len=(i-W)
  if (!(j=jj=(char *)calloc(sizeof(char),(i-W)+1)))
    {
      perror("calloc");
      exit(-1);
    }
  for(  ; i > W  ;i--,jj++) *jj=*(i-1); // reverse copy
  for(   ; *i && (*i == *j);i++,j++ ); //compare
  return !*i ; //  true if end reached.
}
   
int main(int argc, char **args)
{
 string phrase;
 for (; getline(cin,phrase); )
   cout << palindrome(phrase.c_str()) << endl;
 return 0;
}



Aquí algunos ejemplos de ejecución. 1 expresa que es palíndromo, 0 que no lo es.

1234
0
1111
1
1221
1
12344321
1
2
1
331133
1
33113
0
   (intro, palabra vacía, que es palindromo)
1


2 versión. Frases que pueden incluir varias palabras separadas por espacios, blancos, tabuladores...
(Nota: Los separadores están "normalizados" por la funcion isspace(int c))



#include <string> // string
#include <iostream>  // cin, cout
#include <cstdlib> //  malloc

#include <cctype> // isspace
#define sp(c) isspace((c)) // shortcut    

using namespace std;

int palindrome(const char* W)
{
  const char *i, *j;
  char *jj;

  for(i=W  ; *i  ;i++) ;
  if (!(j=jj=(char *)calloc(sizeof(char),(i-W)+1))) // len=(i-W)
    {
      perror("calloc");
      exit(-1);
    }
  for(  ; i > W  ;i--,jj++) *jj=*(i-1); // reverse copy
  const char *b; // key!
  for ( ; *i && (sp(*i)||sp(*j) || (*i==*j)); i+=(*i==*j)||sp(*i), j+=(*b==*j)||sp(*j)) b=i;
  return !*i ; //  true if end reached.
}

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


Algunso casos de prueba

dabale arroz a la zorra el              abad
1
dabale arroz a la zorra el abad
1
dabale arroz al zorro el  abad
0
              (30 espacios en blanco e intro)
1


Lo que pasa es que no me da tiempo a explicarlo. Si, se que mi escritura del for puede desconcertar a algunos, pero se trata de un doble avance...de los punteros... Dos comentarios más :

  • con python no haria falta la variable "b" porque puede simular la asignacion simultanea.
  • se puede prescindir una de las variables, "j" o "jj" (la que quede debe se (char *)), a cambio de un bucle similar al primero para rescatar de nuevo la longitud de la cadena, antes de el último for de comparación 

Que te sirva! Y perdón por los acentos que faltan!
#76
Cita de: MAFUS en 30 Abril 2018, 06:51 AM
Esto es por conio.h que es una librería de Borland y estás usando otro compilador que no la tiene.

Empiezo por la solución. Prueba a poner, como solución local:


...
#include<conio.h>
#define getchr  _getchr

using namespace std;

int main(){
....


a ver qué pasa...(no he podido probar porque tengo Linux...)

Como dice MAFUS, pertenecían a Borland, pero Microsoft las mantiene en su SDK, para garantizar compatibilidad con el legacy software

https://docs.microsoft.com/en-us/cpp/c-runtime-library/console-and-port-i-o

Pero, bien claro lo advierte...

This API cannot be used in applications that execute in the Windows Runtime. For more information, see CRT functions not supported in Universal Windows Platform apps.


Es  una pena que para un programa que no pretende hacer una aplicación, sino un sencillo algoritmo con entrada-salida por consola se pierda compatibilidad con el restro de plataformas linux, mac, freebsd...

Las recomendaciones al respecto, son...

  • No uses ni "_getchr()", ni system("PAUSE"). Esta última, aunque te funcione, lo que hace es abrir todo un proceso costoso que NADA tiene que ver con tu algoritmo.... Tendría sentido en programación Batch* de windows.
    Ejecuta el programa desde una consola abierta expresamente para eso, no lanzándolos desde el IDE... busca dónde se guarda el ".exe" y des la consola lo ejecutas. Así todos los símbolos se quedan para que los puedas ver
  • Si aún quieres lanzarlos desde el IDE, (Visual C++, Dev-Cpp....) prueba a poner un sencillo "cin >> ch" , con "ch" de tipo "char"... que espera latente a leer un caracter (más el enter). As'i al menos, lo podran ejecutar otras plataformas no windows. Pero ojo, estas marcando un "protocolo"  de entrada totalmente inútil... Mejor ejecuta desde consola!

*... Hace poco en estos foros pude ver a uno de los mejores programadores de Batch "del mundo"... creo que era de Méjico.... Increible lo que podia hacer con el command.com. (Sabe algo alguien de él?)
#77
Cita de: oq.JULIO.po en 26 Abril 2018, 02:28 AM
Okok muchas gracias a ambos, y si quisiera que se inicializara desde el valor de la variable "n" dada por el usuario,y termine hasta que sea igual a 3?

Un poco más raro... pero igual de bonito.

La expresión


c=(N%3==0)*N


se evalúa de la siguiente manera: Si N es divisible entre 3, entonces (N%3==0) es 1, y entonces c, vale  1*N . En otro caso, pues 0.

#include <stdio.h>
#include <assert.h>
   
   
/*
 P : M >= 3
 Q : c = sum i : 3 <= i <= M and (i%3==0) : i
   
 I : Q[M/n] and 3 <= n <= M
 B : n > 3
   
 Quota (n) = n - 3 >= 0
 Step : n = n - 1
 Restore : c = c + (n-1)*\chi((n-1)%3==0)
     
*/
   
#define DEBUG
   
unsigned int mult3(const unsigned int N)
{
 assert(N>=3);
 unsigned int n,c;
 for(n=N,c=(N%3==0)*N;n>3;n--)
   {
#ifdef DEBUG
     if (n%3==0) printf("%d ",n);
#endif
     if (((n-1)%3==0)) c+=(n-1);
   }
#ifdef DEBUG
     printf("%d ",3);
#endif
 return c;
}
   
   
   
int main()
{
 unsigned int M;
 int e;
 for ( ; (e=scanf("%u",&M))==1;)
   printf(" --> %u\n",mult3(M));
 if (e!=EOF)
   {
     printf("Not a integer");
     return -1;
   }
 return 0;
}


La salida del programa da

3
3  --> 3
4
3  --> 3
5
3  --> 3
6
6 3  --> 9
7
6 3  --> 9
8
6 3  --> 9
9
9 6 3  --> 18
10
9 6 3  --> 18

#78
Hola!

Cita de: oq.JULIO.po en 25 Abril 2018, 06:40 AM
... que haya contenidos en un número dado por el usuario.
Si digito un 9 la suma de sus múltiplos debería dar 3+6+9=18

Yo diría mejor

contenidos en un rango empezando desde 3 hasta un número (mayor o igual que 3) dado por el usuario.


La sintaxis de la instrucción de control "for", a no dudarlo, una de las señales más características del lenguaje C, sobretodo porque es tan versátil que su expresividad es equivalente a la de la instrucción "while"...
Esto no era así en otros lenguajes de su época, como el mítico Pascal, en el que se usaba como azucar sintáctico de una construcción while particular (donde había una variable  contadora "n", que se comparaba contra una expresión "n=e(...)" y se incrementaba o disminuía  en un valor constante 1,2...)

Tiene 4 partes
for (init; B ; step) body
que vienen a coincidir con lo que en algoritmia clásica se conoce como


  • init : donde se dan valores a las variables al principio
  • B : guarda que determina cuándo termina su ejecución. (Después del init y del step en segundas vueltas)
  • step : incremento de variable, para que el bucle progrese hacia su terminación (después del body)
  • body: aproxima el cómputo parcial a la solución definitivadespues de evaluar la guarda y antes de step

En el cuerpo del bucle pueden aparecer instrucciones como break; o continue, y aunque muy útiles en programación se sistemas y en el mundo real, en algoritmia clásica son el "patito feo" que rompe la llamada "programación estructurada" o "composicional"... Pero esto es otro tema aparte..... C no fue hecho para estudiar algoritmia, sino para la programación de sistemas operativos, y es ahí donde encuentran todo su valor...


Ahi va una solución a tu problema.
Los comentarios tienen más importancia en cursos avanzados de algoritmia. Por el momento fífate en la rutina mult3. Después intenta programarla en sentido descendente (con nn--...)



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


/*
 P : M >= 3
 Q : c = sum i : 3 <= i <= M and (i%3==0) : i

 I : Q[M/n] and 3 <= n <= M
 B : n < M

 Quota (n) = M - n >= 0
 Step : n = n + 1
 Restore : c = c + (n+1)*\chi((n+1)%3==0)
 
*/

#define DEBUG

unsigned int mult3(const unsigned int N)
{
 assert(N>=3);
 unsigned int n,c;
#ifdef DEBUG
      printf("%d ",3);
#endif
 for(n=c=3;n<N;n++)
   {
     if (((n+1)%3==0)) c+=(n+1);
#ifdef DEBUG
     if ((n+1)%3==0) printf("%d ",n+1);
#endif
   }
 return c;
}



int main()
{
 unsigned int M;
 int e;
 for ( ; (e=scanf("%u",&M))==1;)
   printf(" --> %u\n",mult3(M));
 if (e!=EOF)
   {
     printf("Not a integer");
     return -1;
   }
 return 0;
}





La salida que da el programa es:


3
3  --> 3
4
3  --> 3
5
3  --> 3
6
3 6  --> 9
7
3 6  --> 9
8
3 6  --> 9
9
3 6 9  --> 18
10
3 6 9  --> 18





#79
Programación C/C++ / Re: [Función fscanf]
23 Abril 2018, 01:14 AM
Código (bash) [Seleccionar]
Cita de: Apazche en 27 Diciembre 2017, 00:39 AM


Mis preguntas son:
¿Por qué el carácter '\n' no lo imprime cuando lo lee?
El número 20 se lo salta al terminar de leer la primera línea, ¿Por qué?
fscanf lee '\n' ?  '\n' es un char, cierto?

Espero sus respuestas :D


Como dices, "\n" es un carácter, pero la directiva de matching "%c", según el manual, salta todos los caracteres "white-space", (entendiendo estos como el spacio, el tablador, el fin de línea... todos los que responden a isspace(int c) ).
Si te fijas en la salida , salta del 19 al 21...

Otra aspecto tiene que ver con printf. Propimaente hablando, el caracter '\n' no es carácter imprimible, segun (isprint(c)) ,  sino de control iscntrl(c). En el caso de "\n" dicen que "debe" hacer un scrolling de 1 y empezar en la primera columna, no que imprima propiamente un caracter...



Una solución pasa por dejar usar las rutinas "high-level IO", los streams, a las de "low-level IO", los "file descriptors".

El incoveniente es que perdemos la funcionalidad de la rutina

long ftell(FILE *stream)


pero que podemos simular con

pos=lseek(fd,0,SEEK_CUR)

Por supuesto, para dar una salida formateada, debo volver a las rutinas "high-level" IO, como printf... Pero es un problema aparte de el de lectura read



Hay otro error, que ya muestro corregido, relatio a la función feof()... Esta función sólo tiene valores coherentes después de haber invocado la correspondiente fscanf, es decir, no puede anticipar si la cabeza lectora ha llegafo a fin de fichero..



Ahí va mi propuesta.


#include <stdlib.h> // exit()...
#include <assert.h> // assert
#include <unistd.h> // open,read,close (Low-level IO),
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> // open,O_RDONLY...
#include <stdio.h> //p printf


#include <ctype.h> // isprint

int main()
{
 char c;
 int n;
 int fd;
 const char *pattern="%d\t%c\t%d\n";
 char row[80];
 if (!(fd=open("texto.txt",O_RDONLY)))
   {
     perror("open");
     exit(EXIT_FAILURE);
   }
 printf("ASCII\tPrint\tPos\n");
 while((n=read(fd,&c,sizeof(char)))> 0)
   {
     assert(isascii(c));
     if ((n=sprintf(row,pattern,c,isprint(c)?c:' ',lseek(fd,0,SEEK_CUR)))<0)
{
 perror("sprintf");
 exit(EXIT_FAILURE);
}
     printf(row);
   }
 if (n==-1)
   {
     perror("read");
     exit(EXIT_FAILURE);
   }
 close(fd);
 exit(EXIT_SUCCESS);
}


Pasándole el fichero de texto propuesto

supholasadkjholasad
adholadsa


El programa arroja la salida siguiente: Cuando es imprimible, imprime su símbolo, cuando es de control, en su lugar, un espacio. (Los números que salen al principio los pone el codgo GeSHi del web, porque si no, perdía el formato de salida... un lío vamos)



ASCII Print Pos
115 s 1
117 u 2
112 p 3
104 h 4
111 o 5
108 l 6
97 a 7
115 s 8
97 a 9
100 d 10
107 k 11
106 j 12
104 h 13
111 o 14
108 l 15
97 a 16
115 s 17
97 a 18
100 d 19
10 20
97 a 21
100 d 22
104 h 23
111 o 24
108 l 25
97 a 26
100 d 27
115 s 28
97 a 29
10 30
#80
Programación C/C++ / Re: Funcion recursiva
8 Abril 2018, 11:50 AM
La programación recursiva... un tema apasionante.

Su origen es anterior a la programación iterativa y, en algunos contextos, se suele referir a ella como una modalidad de programación declarativa. ¿por qué? Porque...

¡ es más sencilla !

Consiste en declarar, no en programar, la expresión que deseas ( Esta sutil distinción se aprecia con la experiencia...).

Cita de: Kinamox en  7 Abril 2018, 02:25 AM


An = 2An-1 + 3
A0 = 1


Fíjate que es prácticamente lo mismo que en la expresión matemática.... No hay "variables" (salvo el parámetro), no hay asignaciones, no hay bucles... Casi parece matemáticas y no computación...

 fun A(in int n) dev int
 {
    case n==0 : dev 1
    case n> 0 : dev 2*A(n-1) + 3
 }


La transcripción a lenguaje como C puede quedar:



#include <stdio.h>

unsigned int A(const unsigned int n)
{
 if (n==0) return 1;
 if (n>0) return (2*A(n-1) + 3);
}

#define MAXIMUM 20

int main(int argc, char *args[])
{
 unsigned int n;
 for( n=0; n<MAXIMUM ; n++)
   printf("A\(%2u\) : %8u\n",n,A(n));
}


La salida da lo siguiente:
A( 0) :        1
A( 1) :        5
A( 2) :       13
A( 3) :       29
A( 4) :       61
A( 5) :      125
A( 6) :      253
A( 7) :      509
A( 8) :     1021
A( 9) :     2045
A(10) :     4093
A(11) :     8189
A(12) :    16381
A(13) :    32765
A(14) :    65533
A(15) :   131069
A(16) :   262141
A(17) :   524285
A(18) :  1048573
A(19) :  2097149



Si quieres una versión más "C-flavour"/NINJA puedes hacer:

unsigned int A(const unsigned int n)
{
 return n?(2*A(n-1)+3):1 ;
}


Cuidadito que el paso de mates a C no es gratis... Más allá de A=29, la función desborda los valores de unsigned int....