Ordenadores con Ubuntu en el Corte Ingles

Según un post que he encontrado mirando las etiquetas de wordpress (Fuente original):
El Corte Inglés está empezando a vender ordenadores con Ubuntu. Ahora mismo se puede comprar aquí un emachines EL1200 por 229€, sólo en Internet, como se puede ver en la captura de pantalla.

Equipo con Ubuntu instaladoEsta muy bien … y espero que cada vez haya más, pero GNU/Linux no solamente sirve para formar ordenadores ultra baratos, hay que luchar por GNU/Linux tambien en maquinas de gama alta. No obstante, me alegra la noticia.

Por si lo quereis comprar:
http://sliceoflinux.com/2010/03/08/el-corte-ingles-vende-ordenadores-con-ubuntu/

Primer día sin SC2 Beta

Escribo este post desde el trabajo, ya que es mi primera mañana sin la beta del SC2 que me dio Blizzard el sabado. El mono es impresionante, y encima luego tengo uni, no se si aguantaré … Solo ayer me hecho como 20 partidas, entre 1vs1 o 2vs2.

Es un puto juegazo, ya en beta y lo será mucho más. Estoy de moemnto jugando como Zerg. Mucha gente dice que Zerg es simplón, ya que simplemente es ir a roaches + hydras, pero no siempre es así. Hay muchas estrategias. No veo a los Zerg tan under como dicen.

La gente dice que estan muy over los protoss pero de momento no he tenido problemas en petarlos, excepto uno que me saco 5 colosos y me peto las hydras. Otra gente dicen que los más overs son los humanos, podría ser, los putos segadores me tocan la moral, y me obligan a proteger a los curros con alguna torre.

Los que no tengis la Beta, podeis jugarla en plan pirata vs el PC. Por defecto la IA que viene no llega ni a A, le falta la I xD. Blizzard lo denomina «Muy fácil», pero es que … como decirlo … ni ataca practicamente. En mediavida leí, que un tipo, ha desarrollado una IA mucho más decente que la de Blizzard.

Benchmark Factorial – Parámetros acumulados

Voy hacer un benckmark de 3 implementaciones de factorial:

Em primer lugar, la implementación más simple y eficiente, por siempre de los jamases, al menos para arquitecturas de Von Newman y monoprocesador:

long factorial_iterativo(long n)
{
	long i, ac = 1;
	for(i=n; i>0; i--)
		ac = ac * i;
	return ac;
}

Despues esta la recursiva lineal, típico ejemplo de recursividad. Fijaos en la linea de la llamada recursiva …

long factorial_recursivo(long n)
{
	if (n == 0)
		return 1;
	else
		return n * factorial_recursivo(n-1);
}

Y esta es la que realmente tenía curiosidad de comparar.  Es un tipo de recursividad que hace que la vuelta en lugar de ser de pila, sea de cola. Es necesario modificar la interfaz y crear una nueva función manejadora que respete la interfaz. Se trata de ir acumulando el resultado como parametro y principalmente que en la linea que se hace la llamada recursiva, solo haya una llamada recursiva.

Esta función, teoricamente implementado en Caml el compilador al pasarlo a código maquina la pasa a iterativa automaticamente. Si esto fuera tambien así en C, podríamos utilizar funciones recursivas, sin miedo a desbordar la pila y sin problemas de redimiento. Y por supuesto ganando la claridad de resolver algunos problemas de naturaleza recursiva.

long _factorial_recursivo_PA(long n, long r)
{
	if (n==0)
		return r;
	else
		return _factorial_recursivo_PA(n-1, n*r);
}

long factorial_recursivo_PA(long n)
{
	return _factorial_recursivo_PA(n, 1);
}

Los resultados son estos:

Seguir leyendo

Señal SIGCHLD – Evitar Zombies

Hace un par de años hice una práctica de sockets, con el típico modelo cliente-servidor donde el servidor da servicio multicliente con fork(). La práctica cumplía los requisitos y los profesores no detectaron problemas.

Realmente la práctica tenía un bug y es que en ocaciones, se quedaban procesos zombies. Realmente el problema es que confie en el código base que nos daban los profesores, que estaba bugeado. Ahora he tenido que reutilizarla para otra asignatura, y ahora ya se cual era el problema.

En sistemas Unix, un proceso puede tener hijos ¬¬, creados mediante fork. Cuando el hijo termina, se envía la señal SIGCHLD al padre. Por defecto, la señal se ignora y se crea un proceso zombie. El padre debe instalar un manipulador de señales para actuar sobre la señal, ese era mi problema. En algunas plataformas Unix, se pueden evitar los zombies explícitamente ignorando la señal SIGCHLD. Sin embargo, instalar un manipulador de señales para SIGCHLD y llamar a wait es la mejor manera de evitar zombies conservando la portabilidad.
El manipulador de la señal:

void sigchld_handler(int s)
{
    while(wait(NULL) > 0);
}

Hay varias funciones o métodos para setear la señal, os pongo 2, el largo(más portable, POSIX) y el corto(desconozco su portabilidad):

    struct sigaction sa;
    sa.sa_handler = sigchld_handler; // manejador

    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    if (sigaction(SIGCHLD, &sa, NULL) == -1)
    {
        perror("Error en sigaction");
        exit(1);
    }

Os dejo la forma más corta y fácil:

signal(SIGCHLD , sigchld_handler);

No hace falta decir que necesitais el «signal.h»

Fuentes: http://es.wikipedia.org/wiki/SIGCHLD

Sony = pWn3d!

Ayer me llama mi novia diciendo, que ha visto en las noticias un bug en la playstation 3 y ha provado su consola (la gorda), y esta afectada. OMG!

El bug consiste en que en el algún momento entre el 28 de febrero y 1 de marzo todas las ps3 del mundo petaron. Es curioso que no importe la región, esto indica que es un bug del reloj interno que va con GMT +0.

Ayer sobre las 23:00 ya salimos del 29 bisiesto virtual en el que estaban todos los relojes internos del mundo y era muy posible que se arreglara el solo, sin parchear nada. Y así ha sido, las consolas han vuelto a funcionar hoy, simplemente corrigiendo el día.

El reloj interno es una marca de tiempo que se utiliza para cuando por ejemplo compras contenido DRM, como peliculas durante 24 horas. Se graba la marca de tiempo del reloj interno y se suma un offset de 24 horas, independientemente de la región. Sino se hiciera asi, podríamos quedarnos la película más de 24 de horas si estuvieramos retrasando el reloj continuamente.

Yo pienso que precisamente por eso, no se ha permitido conectar a PSN, además de por todas las incoherencias en logros, principalmente por evitar comprar contenido DRM en sistemas bugeados.

Le dejo a Sony una mini práctica que hice en primero para mostrar el calendario de cualquier año (>=1) o para para mostrar el mes actual:

program Actividad3;
{
Actividad 3
por Ricardo Marmolejo García
1º Ingienería Técnica Informática de Gestión
}

uses crt,dos;

const
   ANCHO_COL = 4;

var
   eleccion:integer;
   que_ano:integer;
   eleccion_str:string;
   que_ano_str:string;
   error:integer;

{
Funciones utilizadas en actividades anteriores:
pintar_marco()
mostrar_texto_centrado()
pintar_creditos()
}

procedure pintar_marco(x1,y1,ancho,alto:byte);
var
   x,y:byte;
   x2,y2:byte;
const
   DOBLE_BARRA_VERTICAL=186;
   DOBLE_BARRA_HORIZONTAL=205;
   ESQUINA_SUPERIOR_IZQUIERDA=201;
   ESQUINA_SUPERIOR_DERECHA=187;
   ESQUINA_INFERIOR_IZQUIERDA=200;
   ESQUINA_INFERIOR_DERECHA=188;

begin
   x2 := x1 + ancho;
   y2 := y1 + alto;

   for x := (x1+1) to (x2-1) do
   begin
      gotoxy(x,y1);
      write(chr(DOBLE_BARRA_HORIZONTAL));
      gotoxy(x,y2);
      write(chr(DOBLE_BARRA_HORIZONTAL));
   end;

   for y := (y1+1) to (y2-1) do
   begin
      gotoxy(x1,y);
      write(chr(DOBLE_BARRA_VERTICAL));
      gotoxy(x2,y);
      write(chr(DOBLE_BARRA_VERTICAL));
   end;

   gotoxy(x1,y1);
   write(chr(ESQUINA_SUPERIOR_IZQUIERDA));
   gotoxy(x2,y1);
   write(chr(ESQUINA_SUPERIOR_DERECHA));
   gotoxy(x1,y2);
   write(chr(ESQUINA_INFERIOR_IZQUIERDA));
   gotoxy(x2,y2);
   write(chr(ESQUINA_INFERIOR_DERECHA));
end;

procedure mostrar_texto_centrado(texto:string;altura:byte);
var
   centro_pantalla,centro_texto:byte;
const
   ANCHO_PANTALLA = 80;
begin
   centro_pantalla := ANCHO_PANTALLA DIV 2;
   centro_texto := length(texto) DIV 2;

   gotoxy(centro_pantalla - centro_texto , altura);
   write(texto);
end;

procedure pintar_creditos();
begin
   textcolor(8);
   mostrar_texto_centrado('ACTIVIDAD 3',23);
   mostrar_texto_centrado(CONCAT('por Ricardo Marmolejo Garc',chr(161),'a - 2006'),24);
   textcolor(15);
end;

////////////////////////////////////////////////////////////////////////////////

function esBisiesto(ano:integer):boolean;
{
ENTRADA: año que queremos evaluar
SALIDA: booleana
OBJETIVO: Nos dice si un año es bisiesto o no
}
begin
   esBisiesto := (ano MOD 4 = 0) AND ((ano MOD 100 <> 0) OR (ano MOD 400 = 0));
end;

function getLimiteDeEsteMes(mes:byte;ano:integer):byte;
{
ENTRADA: mes y ano
SALIDA: Nos devuelve el número del último dia del mes
OBJETIVO: Nos permite obtener el límite de cada mes
}
begin
   case mes of
      1:getLimiteDeEsteMes := 31;
      2:if(esBisiesto(ano)) then
          getLimiteDeEsteMes := 29
        else
          getLimiteDeEsteMes := 28;
      3:getLimiteDeEsteMes := 31;
      4:getLimiteDeEsteMes := 30;
      5:getLimiteDeEsteMes := 31;
      6:getLimiteDeEsteMes := 30;
      7:getLimiteDeEsteMes := 31;
      8:getLimiteDeEsteMes := 31;
      9:getLimiteDeEsteMes := 30;
      10:getLimiteDeEsteMes := 31;
      11:getLimiteDeEsteMes := 30;
      12:getLimiteDeEsteMes := 31;
   end;
end;

procedure parchear_diasemana(VAR diasemana:WORD);
{
ENTRADA: dia de la semana
OBJETIVO: si es domingo cambia el 0 a 7 quedando definido de 1-7
}
begin
   if(diasemana = 0) then
     diasemana := 7;
end;

function imprimir_un_mes(INICIO,FIN,diasemana,mes:byte):byte;
{
ENTRADA:
INICIO -----> inicio por el que comienza el mes , lo lógico es que sea 1 o el dia actual
FIN --------> fin para el mes , suele venir dado por getLimiteDeEsteMes()
diasemana --> dia de la semana del 1-7 en que comienza el mes
mes --------> del 1-12 mes que se va a imprimir
SALIDA:       dia de la semana del siguiente mes , con esto si llamamos reiteradas veces a esta función
              encadenamos los meses y lo que hacemos es imprimir un calendario
OBJETIVO: imprimir un mes
}
var
     i:byte;
     nombre_mes:string;
     ano_actual,mes_actual,dia_actual,diasemana_actual:word;

   function getNombreMes(mes:byte):string;
   {
   ENTRADA: mes del 1 al 12
   SALIDA: Nombre en String del mes
   OBJETIVO: Crea una relación del número del mes con su nombre
   }
   begin
      case mes of
         1:getNombreMes := 'Enero';
         2:getNombreMes := 'Febrero';
         3:getNombreMes := 'Marzo';
         4:getNombreMes := 'Abril';
         5:getNombreMes := 'Mayo';
         6:getNombreMes := 'Junio';
         7:getNombreMes := 'Julio';
         8:getNombreMes := 'Agosto';
         9:getNombreMes := 'Septiembre';
         10:getNombreMes := 'Octubre';
         11:getNombreMes := 'Noviembre';
         12:getNombreMes := 'Diciembre';
      end;
   end;

   procedure mostrar_cabezera_de_un_mes(titulo_del_mes:string);
   {
   ENTRADA: Entregamos el String del mes
   OBJETIVO: Nos muestra una cabezera del mes
   }
   begin
      writeln;
      writeln;
      textcolor(14);
      writeln(UPCASE(titulo_del_mes):ANCHO_COL*5);
      textcolor(7);
      writeln;
      write('   L   M   X   J   V   S');
      textcolor(12);
      writeln('   D');
      textcolor(15);
      writeln;
   end;

   procedure tabular_en_funcion_del_dia_de_la_semana(diasemana:byte);
   {
   ENTRADA: dia de la semana
   OBJETIVO: Nos tabula los meses para que cuadren los dias de la semana
            si empezamos en 1 (lunes) hay 0 tabulaciones
            si empezamos en 2 (martes) hay 1 tabulaciones
            si empezamos en 3 (miercoles) hay 2 tabulaciones
            si empezamos en 4 (jueves) hay 3 tabulaciones
            ...
            si empezamos en n hay (n-1) tabulaciones
   }
   var
      i:byte;
   begin
      for i:=1 to diasemana-1 do
          write('':ANCHO_COL);
   end;
begin
   GetDate(ano_actual,mes_actual,dia_actual,diasemana_actual);
   parchear_diasemana(diasemana_actual);
   nombre_mes := getNombreMes(mes);
   mostrar_cabezera_de_un_mes(nombre_mes);
   tabular_en_funcion_del_dia_de_la_semana(diasemana);
   for i:=INICIO to FIN do
   begin
      textcolor(15);
      // aqui no miro año , asi que puede ocurrir que coloree el dia de un año que tenga el mismo dia de la semana
      if(i = dia_actual) AND (mes = mes_actual) AND (diasemana = diasemana_actual) then
          textcolor(10)
      else if(diasemana = 7) then
          textcolor(12);

      write(i:ANCHO_COL);

      if(diasemana = 7) then
      begin
           writeln;
           diasemana := 1;
      end
      else
          diasemana := succ(diasemana);
   end;
   imprimir_un_mes := diasemana;
end;

procedure imprimir_calendario(que_ano:integer);
{
ENTRADA: Año del calendario que quieres ver
OBJETIVO: Mostrar el calendario
}
var
   i:byte;
   diasemana:byte;

  function CalcularPrimerDiaDeLaSemanaDeUnAno(ano:integer):byte;
  {
Esta función me ha costado pensarlo y no se si esta bien , he supuesto lo siguiente :
He observado que el 1 de enero del 2005 es Sabado(6) , el 1 de enero del 2006 es domingo (7),
el 1 de enero del 2007 es lunes (1) , el 1 de enero del 2008(bisiesto) es miercoles(3) (se ha saltado el martes)
de aqui deduzco una función recursiva. Supongo que el año 1 empieze en lunes ,(realmente empeze con 2006)
El año 2 se define:
   si el año anterior a 2 es bisiesto entonces
      El año 2 sera el año anterior a 2 + 2
   sino (no es bisiesto)
      El año sera el año anterior + 1
Para reiniciar al llegar a domindo uso MOD 7
Con esto consigo esta sucesión : 1 , 2 , 3 , 4  , 6 , 7 , 1 , 2 , 4  , 5 , 6 , 7 , 2 , 3 ...
Consigo definir todos los dias de la semana de los unos de eneros del año 1 en adelante
  ENTRADA: año
  SALIDA: dia de la semana del año introducido
  OBJETIVO: Al imprimir el calendario de un año , para definir este año solo necesito saber el dia de la semana del 1 de enero
  }
  begin
     if (ano <= 1) then         CalcularPrimerDiaDeLaSemanaDeUnAno := 1      else         if(esBisiesto(ano-1)) then           CalcularPrimerDiaDeLaSemanaDeUnAno := CalcularPrimerDiaDeLaSemanaDeUnAno(ano-1) + 2         else           CalcularPrimerDiaDeLaSemanaDeUnAno := CalcularPrimerDiaDeLaSemanaDeUnAno(ano-1) + 1;       if CalcularPrimerDiaDeLaSemanaDeUnAno > 7 then
          CalcularPrimerDiaDeLaSemanaDeUnAno := CalcularPrimerDiaDeLaSemanaDeUnAno MOD 7;
  end;

   procedure imprimir_cabezera_calendario();
   {
   OBJETIVO : Imprime un Titulo en color , indicando el AÑO
   }
   begin
      writeln;
      textcolor(10);
      writeln('               A',chr(164),'o ',que_ano);
      textcolor(15);
   end;

begin
   diasemana := CalcularPrimerDiaDeLaSemanaDeUnAno(que_ano);
   imprimir_cabezera_calendario();
   for i:= 1 to 12 do
     diasemana := imprimir_un_mes(1,getLimiteDeEsteMes(i,que_ano),diasemana,i);
end;

procedure imprimir_desde_HOY_hasta_el_proximo_mes();
{
OBJETIVO: Imprime un periodo aproximado de un mes , exactamente desde el dia X del mes actual
hasta el dia X del siguiente mes
}
var
   ano,mes,dia,diasemana:word;

   function getProximoMes(mes:integer):byte;
   {
   ENTRADA : Mes de referencia
   SALIDA : Siguiente mes respecto al mes de referencia
   OBJETIVO : Saber el proximo mes
   }
   begin
      if(mes = 12) then getProximoMes := 1
      else if(mes > 12) then getProximoMes := mes MOD 12
      else getProximoMes := mes+1;
   end;
begin
   GetDate(ano,mes,dia,diasemana);
   parchear_diasemana(diasemana);

   // imprimo el actual mes
   diasemana := imprimir_un_mes(dia, getLimiteDeEsteMes(mes,ano) , diasemana , mes               );
   // imprimo el proximo mes , sabiendo el dia de la semana que me devolvio la anterior
                imprimir_un_mes(1  , dia                         , diasemana , getProximoMes(mes));
end;

begin
   repeat
      clrscr;
      textcolor(15);
      pintar_marco(10,5,60,15);
      gotoxy(15,8);   writeln('1 . Imprimir un MES desde hoy hasta el proximo mes');
      gotoxy(15,10);  writeln('2 . Imprimir un calendario');
      gotoxy(15,12);  writeln('3 . Salir');
      pintar_creditos();
      gotoxy(15,16);
      write('Elije una opcion [1-3] : ');
      readln(eleccion_str);
      val(eleccion_str,eleccion,error);
      clrscr;
         case eleccion of
            1:
            begin
                 imprimir_desde_HOY_hasta_el_proximo_mes();
                 readkey;
            end;
            2:
            begin
                 writeln('Calendario del a',chr(164),'o ? (mayor o igual que a',chr(164),'o 1) : ');
                 readln(que_ano_str);
                 val(que_ano_str,que_ano,error);
                 if(error = 1) OR (que_ano < 1) then que_ano := 1;
                 clrscr;
                 imprimir_calendario(que_ano);
                 writeln;writeln;
                 readkey;
            end;
            3://salir
            else
            begin
                 mostrar_texto_centrado('Opcion incorrecta',10);
                 readkey;
            end;
         end;
   until(eleccion = 3);
end.