Towers of Hannoi

This is the source code of the mathematical puzzle game written in python2, where its graphical appearence is based on the gtk+2 library. It’s a simple GUI application, which lets you play this game with a different number of disks.
snapshot of the game
toh.py:

#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import gtk
import sys
import cairo
from gtk import gdk

class Towers( gtk.DrawingArea ):
  def __init__( self ): 
    gtk.DrawingArea.__init__( self )
    self.set_size_request( 300, 200 )
    self.connect( "expose-event", self.on_expose )
    self.connect( "button-press-event", self.on_click )

    self.set_events( gdk.BUTTON_PRESS_MASK )

    self.set_disc_num( 3 )

  def on_expose( self, widget, event ):
    cr = self.window.cairo_create( )
    
    cr.rectangle( event.area.x, event.area.y, 
                  event.area.width, event.area.height )
    cr.clip( )
		
    self.draw( cr )
    return False

  def on_click( self, widget, event ):
    okey = False
    om = int( ( event.x - self.x ) // ( self.w / 3.0 ) )
    
    if event.button == 1:
      to = om + 1
      okey = True
    elif event.button == 3:
      to = om + 2
      okey = True
    if okey: self.move_disc( om, to % 3 )
    return True

  def move_disc( self, om, to ):
    def find_top( num ):
      for i in range( self.disc_num - 1, -1, -1 ):
        if self.tower[om] & ( 1 << i ):
          return i
    if not self.tower[om]: return
    top_disc = 1 << find_top( self.tower[om] )
    if top_disc < self.tower[to]: return
          
    self.tower[om] ^= top_disc 
    self.tower[to] |= top_disc
        
    self.queue_draw( )
          
  def draw( self, cr ):
    rect = self.get_allocation( )
    self.w = min( rect.width, 3.0 / 2.0 * rect.height )
    self.h = min( rect.height, 2.0 / 3.0 * self.w )
    self.w = 3.0 / 2.0 * self.h
    self.x = ( rect.width - self.w ) / 2.0
    self.y = ( rect.height - self.h ) / 2.0 

    #cr.set_source_rgb( 0, 0, 0 )
    #cr.rectangle( 0, 0, self.w, self.h )
    #cr.stroke( )

    #cr.set_source_rgb( 1, 1, 1 )
    #cr.rectangle( 0, 0, rect.width, rect.height )
    #cr.stroke( )

    for n in range( 3 ):
      self.draw_tower( cr, n )

  def draw_tower( self, cr, n ):
    cr.set_source_rgb( 0.375, 0.25, 0.125 )
    cr.save( )

    lw = 5 * cr.get_line_width( )
    cr.set_line_width( lw )
    ofs = 10
		
    cr.move_to( self.x + ofs + n * self.w / 3.0, self.y + self.h - ofs )
    cr.line_to( self.x + ( n + 1 ) * self.w / 3.0 - ofs, self.y + self.h - ofs )
		
    cr.move_to( self.x + ( n + 1.0 / 2.0 ) * self.w / 3.0, self.y + self.h - ofs )
    cr.line_to( self.x + ( n + 1.0 / 2.0 ) * self.w / 3.0, self.y + ofs )

    cr.stroke( )
      
    ofs1 = ofs + 1.0 / 5.0 * self.w / 6.0
    lw1 = 4 * lw 
    fac = 10
    cr.set_line_cap( cairo.LINE_CAP_ROUND )
    cr.set_line_width( lw1 )
    j = 0
    for i in range( self.disc_num ):
      cr.set_source_rgb( 0.04 * i, 0.17 * i, 0.13 * i )
      if self.tower[n] & ( 1 << i ):
        cr.move_to( self.x + ofs1 + fac * i + n * self.w / 3.0,
                    self.y + self.h - ofs - ( lw + lw1 ) / 2.0 - j * lw1 )
        cr.line_to( self.x + ( n + 1 ) * self.w / 3.0 - ofs1 - fac * i,
                    self.y + self.h - ofs - ( lw + lw1 ) / 2.0 - j * lw1 )
        cr.stroke( )
        j = j + 1
          
    cr.restore( )

  def set_disc_num( self, num ):
    self.disc_num = num

    self.tower = [ ( 1 << num ) - 1, 0, 0 ]
    
    self.queue_draw( )


class Toh( gtk.Window ):
  def __init__( self ):
    gtk.Window.__init__( self )
    
    self.set_title( "The Towers of Hannoi" )
    self.set_border_width( 3 )
    self.connect( "destroy", gtk.main_quit )
    
    label = gtk.Label( "Set up the number of discs" )
    towers = Towers( )
		
    adjustment = gtk.Adjustment( 3.0, 1.0, 6.0, 1.0 )
    spin = gtk.SpinButton( adjustment, 0, 0 )
    spin.connect( "value-changed", self.on_click, towers )
    
    hbox = gtk.HBox( False, 5 )
    hbox.pack_start( label, False, False )
    hbox.pack_start( spin, False, False )
    
    vbox = gtk.VBox( False, 5 )
    vbox.pack_start( hbox, False, False )
    vbox.pack_start( towers )
    
    self.add( vbox )
    self.show_all( )

  def on_click( self, spin, towers ):
    towers.set_disc_num( spin.get_value_as_int( ) )


def main( ):
  Toh( )
  gtk.main( )


if __name__ == "__main__":
  try:
    main( )
  except( KeyboardInterrupt ):
    sys.exit( 0 )
Advertisements

Simple GUI application with GTK+

Introduction

In this post you will see what steps are required to create a simple graphical application under gnu/linux. For this purpose  we will use GTK+. If you have never heard about it, it’s a big collections of libraries behind GNOME.
source code of “simple.c”

/* First, we need to import the gtk+ library set. */
#include <gtk/gtk.h>

struct _Widgets
{
  GtkWidget *window, *hbox, *entry, *button, *vbox, *label;
};

typedef struct _Widgets Widgets;

static void button_cb( GtkButton *, Widgets * );

int main( int argc, char **argv )
{
  /* We declair pointers to the widgets. */
  Widgets *widgets;

  /* We need to call this initialization function before we can do any
   * other function calls. */
  gtk_init( &argc, &argv );

  widgets = g_slice_new( Widgets );

  /* First, an empty window is created. */
  widgets->window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
  gtk_window_set_title( GTK_WINDOW( widgets->window), "A Simple Example" );
  gtk_widget_set_size_request( widgets->window, 250, -1 );

  g_signal_connect( widgets->window, "destroy",
		    G_CALLBACK( gtk_main_quit ), NULL );

  widgets->entry = gtk_entry_new( );
  widgets->label = gtk_label_new( NULL );
  widgets->button = gtk_button_new_with_label( "click me!" );

  g_signal_connect( widgets->button, "clicked",
		    G_CALLBACK( button_cb ), widgets );

  widgets->hbox = gtk_hbox_new( FALSE, 0 );
  gtk_box_pack_start_defaults( GTK_BOX( widgets->hbox ), widgets->entry );
  gtk_box_pack_start( GTK_BOX( widgets->hbox ), widgets->button,
		      FALSE, FALSE, 0 );

  widgets->vbox = gtk_vbox_new( FALSE, 0 );
  gtk_box_pack_start( GTK_BOX( widgets->vbox ), widgets->hbox,
		      FALSE, FALSE, 0 );
  gtk_box_pack_start( GTK_BOX( widgets->vbox ), widgets->label,
		      TRUE, TRUE, 0 );

  gtk_container_add( GTK_CONTAINER( widgets->window ), widgets->vbox );

  gtk_widget_show_all( widgets->window );

  gtk_main( );

  return 0;
}

static void button_cb( GtkButton *button, Widgets *widgets )
{
  gtk_label_set_text( GTK_LABEL( widgets->label ), "clicked" );
}
$ # it's time to compile simple.c
$ gcc -o simple simple.c $( pkg-config --libs --cflags gtk+-2.0 )
$ ./simple

ошибка монтирования /dev на /root/dev

Однажды при включении одного из старых лэптопов появилась похожая ошибка:

mount: mounting /dev/disk/by-uuid/c6060118-cc51-439d-9a03-ad971a9de4cc on /root
failed: Invalid argument
mount: mounting /dev on /root/dev failed: No such file or directory
mount: mounting / sys/ on root/sys failed: No such file or directory
mount: mounting /proc on /root/proc failed: No such file or dirctory
Target filesystem doesn’t have /sbin/init.
No init found. Try passing init= boot arg

BusyBox v1.10.2 (Ubuntu 1:1.10.2.2ubuntu7) built-in shell (ash)

(initramfs)

что конечно мгновенно вызвало у меня “панику, панику”. Ведь это скорее всего означает, что полетел винчестер и полет этот будет не долгим.

Если повезет, то может все оказаться не так уж и плохо и если есть “ubuntu live cd” под рукой, то систему возможно удастся восстановить. Для этого достаточно загрузить “живую сессию” с диска, открыть терминал(в гноме: alt+f2 и набор gnome-terminal) и ввести следующую команду:

sudo fdisk -l

которая не смотря на провалы в памяти и отчаянные попытки пользователя вспомнить, где же была им установлена его система, выведет на экран эту весьма полезную информацию (что-то вроде этой).

Disk /dev/sda: 160.0 GB, 160041885696 bytes
255 heads, 63 sectors/track, 19457 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000b7921

Device Boot Start End Blocks Id System
/dev/sda1 * 1 18709 150274048 83 Linux
/dev/sda2 18709 19458 6013953 5 Extended
/dev/sda5 18709 19458 6013952 82 Linux swap / Solaris

После чего можно попытаться восстановить файловую систему (ext3 или ext4), воспользовавшись журналом, про помощи следующей команды, и в случае успеха системой снова можно пользоваться.

sudo e2fsck -fyv /dev/sda1

ps: ну а если даже и диска под рукой рядом не оказалось, то и тут не стоит окончательно отчаиваться. По идее, достаточно постоянно пытаться загрузить компьютер, и где-то на сороковой попытке монтирования, система сжалится над вами и включится автоматическая проверка файловой системы на ошибки, которая вероятней всего восстановит диск и систему можно будет запустить;) удачи!

Unterstreichen und durchstreichen von Text in Latex

Zum hervorheben von Textpassagen in Latex bieten sich im Package ulem mehrere Möglichkeiten an.

Nach dem das Package hinzugefügt ist

\usepackage{ulem}

stehen folgende Befehle zu Verfügung:

\uline{important}  % unterstreichen
\uuline{urgent}    % doppelt unterstreichen
\uwave{boat}       % unterschlängeln
\sout{wrong}       % durchstreichen
\xout{removed}     % ausstreichen mit //////.

Beispiele
Um die gewünschten Stellen noch mit Farbe gekennzeichnen, kann man noch eigene Latex-Befehle definieren. Dafür braucht man das entsprechende Packet color.

\usepackage{color}

Die möglichen neuen Befehle rem und add um die Textabschnitte, die entfernt bzw. hinzugefügt werden müssen, deutlicher zu markieren, werden exemplarisch durch

\newcommand{\rem}[1]{\textcolor{red}{\sout{#1}}}
\newcommand{\add}[1]{\textcolor{blue}{\uline{#1}}}

eingeführt. Diese können ab sofort in einer tex-Datei eingesetzt werden:

This is a text line. \rem{This text was removed.} \add{This text was added.} This is another text line.

Nachdem die tex-Datei erfolgreich kompiliert wird, wird die entsprechende Stelle des Dokumentes wie folgt aussehen:Beispiel