Even Dummies Wear Seatbelts

Bardzo ciekawa reklama propagująca zapinanie pasów bezpieczeństwa, wyprodukowany przez Fińskie Ministerstwo Transportu.

Odległość Levenshteina przy porównywaniu ciągów znaków

Zwykłe porównywanie stringów czy to w php czy asp, sprowadza się do porównywania napisów znak po znaku i wyniku w postaci true lub false. Czasami jednak potrzebujemy porównać napisy powołując się nie na ich bezpośrednią równość, ale na ich podobieństwo.

Jednym z prostszych algorytmów, który pozwoli nam na zbadanie podobieństwa dwóch ciągów znaków jest algorytm Levenshteina, określający tzw. odległość Levenshteina.

Algorytm w oparciu o zdefiniowane wcześniej operacje proste (np. wstawienie znaku, usunięcie znaku, zmiana znaku na inny) określa najmniejszą liczbę operacji, potrzebnych do transformacji pierwszego napisu w drugi. Łatwo sobie wyobrazić, że dla identycznych napisów odległość Levenshteina będzie równa 0, natomiast dla dwóch całkowicie różnych napisów, będzie równa liczbie znaków dłuższego z ciągów. Krótko mówiąc im mniejsza odległość, tym napisy są bardziej do siebie podobne.

Algorytm ten można modyfikować dodając np. nowe operacje, lub przypisując operacjom wagi.

Warto zauważyć, że PHP dostarcza nam własną implementację algorytmu Levenshteina, możemy jej użyć wywołując funkcję levenshtein.

int levenshtein ( string $str1, string $str2 [, int $cost_ins, int $cost_rep, int $cost_del] )

Natomiast w C# porównywaniem string’ów musimy się zająć sami. Przykładowa implementacja może wyglądać na przykład tak:

public static int LevenshteinDistance(String s1, String s2)
{
	const int cost_ins = 1;
	const int cost_del = 1;
	const int cost_sub = 1;
 
	int n1 = s1.Length;
	int n2 = s2.Length;
 
	int[] p = new int[n2+1];
	int[] q = new int[n2+1];
	int[] r;
 
	p[0] = 0;
	for( int j = 1; j <= n2; ++j )
	{
		p[j] = p[j-1] + cost_ins;
	}
 
	for( int i = 1; i <= n1; ++i )
	{
		q[0] = p[0] + cost_del;
		for( int j = 1; j <= n2; ++j )
		{
			int d_del = p[j] + cost_del;
			int d_ins = q[j - 1] + cost_ins;
			int d_sub = p[j - 1] + (s1[i - 1] == s2[j - 1] ? 0 : cost_sub);
			q[j] = Math.Min( Math.Min( d_del, d_ins ), d_sub );
		}
		r = p;
		p = q;
		q = r;
	}
	return p[n2];
}

Wynikiem funkcji Levenshteina jest liczba całkowita. Co jednak zrobić gdy na podstawie porównania ciągów znaków chcemy je klasyfikować? Liczba całkowita nie jest w tym wypadku zbyt wymowna. Lepszym pomysłem jest uzależnienie wyniku od maksymalnej długości ciągu.

Przykład:

public static float LevenshteinTextComparison(String s1, String s2)
{
	if (s1.Equals(String.Empty) && s2.Equals(String.Empty))
	{
		return 1;
	}
	return 1 - ((float)LevenshteinDistance(s1, s2) / (float)Math.Max(s1.Length, s2.Length));
}

Teraz zamiast mało mówiącej liczby całkowitej, otrzymujemy liczbę rzeczywistą z zakresu <0, 1> określającą podobieństwo napisów. Im bliżej jedynki tym ciągi są bardziej podobne i w drugą stronę, im bliżej zera, tym ciągi bardziej się od siebie różnią.

Przydatne linki:

http://pl.wikipedia.org/wiki/Odległość_Levenshteina
http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance

Zdjęcia w Blogger Play

Matt Cutts na swoim blogu zwrócił uwagę na uzależniające działanie ;) Blogger Play. Szczerze mówiąc jest to moje pierwsze spotkanie z tym bardzo prostym i zarazem wciągającym serwisem.

Blogger Play to slideshow wyświetlający zdjęcia, które są aktualnie wrzucane do systemu Blogger przez ludzi na całym świecie.

Blogger Play

Warto zauważyć, że Flickr również posiada podobną funkcjonalność.

Kontrolki kompozytowe w ASP.NET a ClientID

Wyprodukowałem sobie dzisiaj bardzo prostą kontrolkę kompozytową. Jej zadaniem jest pokazywanie i chowanie div’a z tekstem. Całość odbywa się tylko po stronie klienta. Normalnie (mam na myśli HTML) byłoby to banalnie proste, niestety nie w ASP.

Div’a zastąpił mi Panel, a przycisk po wciśnięciu którego pojawia się panel, powstał jako oddzielna kontrolka (także kompozytowa). Wszystko ładnie złożyłem i opakowałem w metodę CreateChildControls(). Ku mojemu zdziwieniu JavaScript wywoływany po wciśnięciu przycisku powodował błąd. Okazuje się, że ClientId panelu jest puste (względnie nie zawiera wartości, której się spodziewam). Dlaczego? Otóż ClientId nie jest dostępne z poziomu metody CreateChildControls(), prawidłową wartość możemy uzyskać dopiero tuż przed wyrenderowaniem kontrolki, czyli np. na preRenderze.

protected override void OnPreRender(EventArgs e)
{
	// tutaj możemy się odwołać do ClientId kontrolek
}

Faktem jest, że unikalne ID tagów html’owych generowanych przez ASP może być zbudowane tylko przy kompletnym drzewie kontrolek, ale czy nie można było zaoszczędzić czasu i napisać o tym w dokumentacji właściwości ClientId?

Koniec urlopu… wracamy do pracy :|

Jestem świeżo po urlopie. Góry, śnieg i narty. Bez laptopa i internetu (no prawie ;) ). Przede wszystkim bez codziennego pośpiechu. Chwila oddechu, która pozwoliła na oderwanie się od problemów, natłoku myśli i informacji. Mała szansa na zerwanie z codzienną rutyną i szarymi ulicami miasta.

Stok narciarski

Wracam, próbuję nadrobić zaległości, zaczynam czytać i na co trafiam?

- Wiesz, oprócz komputerów jest jeszcze rzeczywistość: kwiaty, drzewa, żywi ludzie…
- To znaczy gdzie, za firewallem?…

Rozbroiło mnie to totalnie :D

Reset iPoda nano

Raz na jakiś czas urządzenia po prostu odmawiają posłuszeństwa i przestają działać tak, jak tego od nich oczekujemy. To samo przydarzyło się mojemu iPodowi. Tuż po tym jak próbowałem podłączyć dwa różne iPody do jednego komputera, jeden z nich (iPod nano) zawiesił się. Co należy zrobić w takiej sytuacji?iPod nano

Czasami po prostu musimy go zresetować, mniej więcej tak, jak to się robi z komputerami. Restart iPoda jest bardzo łatwą czynnością, należy zaznaczyć, że nie spowoduje utraty muzyki, plików ani ustawień.

  1. Sprawdź czy iPod jest odblokowany, przycisk na spodzie odtwarzacza powinien być przesunięty w lewo, tak by nie było widać pomarańczowego tła.
  2. Naciśnij jednocześnie i przytrzymaj przez 10 sekund przyciski “Menu” i “Select” (to ten po środku kółka).

Po zresetowaniu, na wyświetlaczu pojawi się logo Apple, a zaraz potem menu główne. :)

Wpis jest luźnym tłumaczeniem artykułu: http://www.methodshop.net/mp3/ipodsupport/restart/index.shtml

Jestem niewidoczny w Gmail Chat

Google wprowadziło w Gmail Chat nowy status: niewidoczny. Teraz możemy się zalogować i przeglądać listę kontaktów, tak aby inni nie wiedzieli, że jesteśmy dostępni. Opcja ta nie jest jeszcze widoczna w polskiej wersji językowej (można ją zobaczyć po zmianie języka na English (US)), nie ma jej również w kliencie Google Talk.

Gmail Chat

Należy zwrócić uwagę, że status ‘niewidoczny’ występuje tylko w nowej wersji Gmaila.

John Cleese chce kredyt gotówkowy

Pojawiła się pierwsza, z serii reklam banku BZ WBK z Johnem Cleesem, legendarnym liderem kabaretu Monty Python. Wszyscy, którzy lubią absurdalny, brytyjski humor na pewno nieźle się uśmieją :).

Sposób na sitemap.xml w bloggerze

Przyglądałem się trochę bloggerowi (bardzo fajny i przyjazny system blogowania, niestety jeśli chodzi o funkcjonalność jest nadal za WordPressem). To co rzuciło mi się w oczy to fakt, że blogger sam z siebie nie oferuje generowania mapy strony w postaci pliku XML (sitemap.xml). Co w takim razie zrobić jeśli chcemy aby mapa naszego bloggerowego bloga była widoczna w Google Webmasters?

Mapę strony możemy zastąpić linkiem do kanału RSS naszego bloga. Wszystko co trzeba zrobić to:

  1. Wejść do Google Webmasters:
    https://www.google.com/webmasters/sitemaps/
  2. Dodać witrynę:
    my-blog.blogspot.com
  3. Dodać mapę witryny. Link do mapy powinien wyglądać następująco:
    my-blog.blogspot.com/atom.xml?redirect=false&start-index=1&max-results=100

Adres ‘my-blog.blogspot.com’ należy oczywiście zastąpić adresem własnego bloga. W ten sposób dodamy mapę strony, która z każdym nowym postem będzie automatycznie uaktualniana.

Informacje zapożyczyłem z grupy googlowej.

Materiały dydaktyczne dla wykładowców i studentów informatyki

Szukając w sieci materiałów do sesji (niestety notatki własne zawiodły) znalazłem bogaty zbiór wykładów i informacji dotyczących studiów informatycznych I i II stopnia.

Strona została przygotowana w ramach projektu “Opracowanie programów nauczania na odległość na kierunku studiów wyższych – Informatyka”, a jej wykonanie zostało sfinansowane ze środków Europejskiego Funduszu Społecznego.

Warto wspomnieć, że za realizację projektu odpowiada grupa składająca się z czołowych polskich uczelni - Uniwersytetu Warszawskiego, Uniwersytetu Jagiellońskiego, Politechniki Poznańskiej i Politechniki Warszawskiej, a zadaniem projektu jest przede wszystkim:

  • Opracowanie programów nauczania dla studiów informatycznych I i II stopnia.
  • Przygotowanie elektronicznych materiałów dydaktycznych, w tym pakietów multimedialnych do prowadzenia zajęć zdalnych.

Strona gromadzi materiały dotyczące 64 przedmiotów, podzielonych w 6 programów nauczania. Każdy program nauczania obejmuje semestralne i godzinowe zestawienie przedmiotów oraz ich sylabusy, specyfikację form zaliczania, punktację ECTS i przede wszystkim materiały dydaktyczne (slajdy, omówienia itd.).

Dzięki projektowi możemy się cieszyć bogatą składnicą informatycznej (i nie tylko) wiedzy.