C, PHP, VB, .NET View RSS

Дневникът на Филип Петров
Hide details



Карат 25 Jul 8:53 AM (3 months ago)

При скъпоценните камъни „карат“ (на английски "carat") е мерна единица за тежест. Един карат е равен на точно 200 милиграма. Думата произлиза от семената на бобовото растение рожков, които средно тежат точно толкова. Те изглеждат неразличими на външен вид, поради което хората си мислели, че са с еднаква маса. Така и започнали да мерят скъпоценни камъни с теглилки и семена. С времето се оказало обаче, че в различни региони на света един и същи скъпоценен камък се оценява с различни карати заради разлика в семената. Така през 1907 г. французите стандартизират карата към по-точна мерна единица - милиграм.

При златото и платината думата „карат“ (на английски "karat") има съвсем различно значение - то означава 1/24-та чистота на метала в сплавта. Например 12 каратово злато ще означава, че ви дават сплав с 12/24 или точно 50% злато в нея. Ето защо чистото злато е точно 24 карата.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Когато отборите не желаят да спечелят… 25 Jul 8:51 AM (3 months ago)

Гледали ли сте футболен мач, в който един от двата отбора упорито не желае да спечели? А мач, в който едни се опитват да си вкарват автогол, а другите им пречат? А един отбор да пази и двете врати?

Първото се е случило на Тайланд срещу Индонезия през 1999 г. на турнира за азиатската купа. Нито един от двата отбора не е желаел да спечели мача, защото при това положение е трябвало да играе срещу силния тим на Виетнам на полуфинала.

Мачът вървял в общи линии ужасно - личало си пълното нежелание за игра и от двата отбора. Все пак голове имало - резултатът до 90 мин бил 2:2 и можело да се каже, че било нещо като нормален футболен мач. При този резултат Индонезия е щяла да "спечели", т.е. да не играе срещу Виетнам. В продължението на мача обаче тайландците се досещат, че могат да си вкарат автогол. Индонезийците надушват намерението им и започват... да бранят чуждата врата. Все пак за №8 от тайландсия отбор се оказва лесно да вкара автогол и неговия тим да загуби. Ето кратък репортаж:

Подобен мач е бил между Западна Германия и Австрия за световната купа през 1982 г. По стечение на обстоятелствата победа на Германия с един или два гола е класирала и двата отбора напред. Германия вкарва в 10-тата минута и от там нататък... следва тежко 80-минутно фиаско с имитация на игра и много малко голови положения.

След този мач ФИФА взима решение последните мачове от груповите фази на световното първенство да се играят едновременно.

Най-странният футболен мач обаче е на Барбадос срещу Гренада, 1994 г.

Барбадос е трябвало да спечели с 2 гола разлика, за да продължи напред в Карибската Купа. Там обаче имало странни правила на турнира - имало правило, че всеки мач трябва да завърши с победител. Така ако даден мач завърши наравно, се играе допълнителни 30 минути, в които важи правило за "златен гол", който... се брои за два гола!

Барбадос водил с 2:0 почти до края на мача, когато Гренада вкарали гол. При резултат 2:1 и оставащи десетина минути до края това означавало, че Гренада продължава напред. Барбадос се опитали да върнат гола, но се оказало трудно - Гренада изпаднали в глуха защита. Краят на мача наближавал и тогава от Барбадос се сетили, че ако си вкарат автогол, могат да докарат равен мач, тогава да има продължения и... потенциално да спечелят със златен гол.

Та Барбадос лесно си вкарват автогол и мачът става 2:2. Остават 3-4 минути до края. Тогава Гренада се сещат, че без значение дали те вкарат гол или получат гол, ще продължат напред. Тогава свинщината започва. От Барбадос естествено не желаят нито да вкарват, нито да получават гол. Получава се крайно нелепа ситуация - Барбадос започват да бранят и двете врати, а Гренада се опитва да вкара в която и да е от тях.

В крайна сметка мачът отива в продължения и Барбадос успяват да продължат напред със златен гол и краен резултат 4:2.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Възпитанието в Япония 21 Jul 6:54 AM (3 months ago)

В Япония на учителите е забранено да се обръщат към учениците с умалителни имена или прякори. Обръщат се към тях само по фамилия. Позволено е да се обръщат към тях с личното им име по изключение, когато са се справили добре с определена задача и си заслужава конкретния човек да се открои пред останалите, но трябва задължително да е придружено с уважителна наставка „-кун“. Само към момиче и то само при извънредно добро представяне, може с наставка „-сан“, което е огромно признание (момчетата нямат възможност за чак такава похвала).

Учениците могат да се обръщат към учителя само по фамилия, при това задължително добавяйки уважителните наставки „-кун“ за мъже и „-сан“ за жени. По много голямо изключение, само когато трябва да се подчертае изключителна признателност за получена откроено индивидуална помощ при някоя задача, се позволява изразяване на благодарност от ученик към учител с изричане на първото му име, но отново задължително с добавена уважителна наставка (по този начин ученикът подчертава, че е много признателен, че учителя му е обърнал лично внимание). Когато последното обръщение не е на място, се счита за неуважително и може да доведе до наказание.

По време на час учениците се обръщат един към друг по фамилия и не използват личните си имена. Изключение от това правило е дадено само когато момиче се обръща към своя съученичка - тогава това може да стане по по първо име, но задължително с наставка „-сан“. За момче към момче, момче към момиче или момиче към момче е забранено.

Извън часовете е позволено на учениците да говорят помежду си по-свободно по лични имена или прякори, като те го правят често с хумористичната наставка „-пон“ или по-рядко между момчета с уважителната „-чан“, но пак като вид закачка. Това обаче се прави само и единствено към ученици от същия пол. Обръщането към ученик от различен пол по лично име без уважителна наставка, а не по фамилия, се счита за любовна закачка. Другите ученици в най-добрия случай само се подиграват на този, който е направил грешката. Би могъл да бъде и „изпортен“ пред ръководството и да си има проблеми. Любовните отношения на територията на училище са напълно забранени - за обикновена целувка се стига до дисциплинарни наказания и дори до изключване.

Има и особен вид йерархия между ученици от различни класове. По-малките задължително се обръщат към по-големите с уважителна форма по същият начин, както към учителите си. По-големите към по-малки се обръщат само по фамилия (без наставка) или понякога с фамилия с наставка „-сан“ към момичета (по-големите момчета не използват уважителната наставка за по-млади момчета).

Това всъщност важи и за цялото общество. Обръщането към японец от чуждо семейство по първо име без някоя от уважителните представки се счита за обида, а когато е към по-възрастен човек - буквално груба обида. Вътре в семействата е позволено обръщане по първо име без наставка или с прякор само от по-възрастен към по-млад. Децата са длъжни да се обръщат към родители и по-възрастни роднини уважително (това ги подготвя и за етикета в обществото). По-свободни взаимоотношения и използването на прякори се вижда само и единствено между много близки хора в техни лични разговори или по време на игра между деца.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Сатрап и маратонско бягане 11 Jul 3:30 AM (3 months ago)

Знаете ли откъде произлизат думите „сатрап“ и откъде идва понятието „маратонско бягане“? Ето малко история от древна Персия, която не се учи в училище...

Според разказ на Херодот, Сисамнес е бил главен съдия по времето на цар Камбиз II (син на Кир II - основателят на Персийската империя), около 500 години преди Христа. Веднъж съдията взел крупен подкуп и издал несправедлива присъда. След като го разкрили, Камбиз II заповядал Сисамнес да бъде заловен и убит по особено жесток начин - одиране на кожата докато е жив.

Според правилата на съда, Сисамнес все пак трябвало да посочи свой заместник, след като „се оттегля“ (макар и принудително). Той решил негов наследник на поста да бъде сина му - Отанес. Кралят приел тази воля, но наредил столът на главния съдия да бъде претапициран с кожата на Сисамнес. По този начин Отанес щял винаги да помни какво може да му се случи ако издаде несправедлива присъда. Така докато бил главен съдия, Отанес бил много справедлив и неподкупен, винаги седейки върху кожата на баща си.

По-късно Камбиз II решил да отвори война и да завладее Египет. Преди да тръгне на поход, тайно наредил на убият брат му - управител на източните провинции. Така решил, че ще се предпази от евентуално предателство. След завладяването на Египет е запомнен с това, че не е зачел религиозните вярвяния на местните жители и е поругал няколко свещенни техни символи.

Междувременно обаче, поради убийството на брат му Смердис (познат още като Бързия), в Персия избухнала гражданска война („междуособната война“). Персийски маг на име Гаумата се представил за брата на Камбиз и вдигнал възстание. Никой не обичал Камбиз II заради тиранията, която е наложил над обикновеното население. Така повечето жреци и магове подкрепили бунта и така фалшивият Смердис бил издигнат за цар на Персия и Вавилон.

Когато разбрал за случващото се във владенията му, Камбиз II се отправил незабавно с армията си, за да си взима обратно властта. В яда се обаче неволно се порязал на собствения си меч. Получила се тежка инфекция и около 20 дни по-късно починал. Армията му се разпиляла из Египет и повечето от войниците никога не се завърнали обратно в Персия.

По времето на управлението на мнимият цар Смердис (всъщност маг Гаумата), Отанес продължил да е главен съдия. Именно той заподозрял измамата със смяната на личността. Знаело се, че Гаумата бил с отрязани уши заради предишни прегрешения, но не можело току така лесно да се накара царят да си покаже ушите пред хората. Затова Отанес помолил собствената си дъщеря Падиме, който била една от жените в харема на царя, да провери дали той има уши или няма.

Падиме по-късно потвърдила, че кралят е с отрязани уши. Така Отанес получил основание и тайно събрал група от още седмина аристократи, с които организирали покушение. Един от тях - Дарий, който имал и кръвна връзка с предишната царска фамилия - лично убил мнимия цар.

Пет дни по-късно бил организиран съвет от седемте заговорници, в който се обсъдила бъдещата форма на управление на страната. Отанес предлагал империята да се управлява като демокрация, Мегабизус искал форма на олигархия, а Дарий настоявал да остане монархия. Спорът бил уреден чрез състезание - чийто кон изцвилел първи след изгрев слънце, щял да спечели. Дарий измамил и така формата на управление останала монархия, а самия той, понеже все пак имал далечна роднинска връзка с истинския Смердис, бил провъзгласен за цар. Оженил се (може би за всеки случай) за единствената дъщеря на Смердис - принцеса Пармис.

В началото на управлението си Дарий I въвел някои нововъведения. Въвел нови златни монети като универсална валута (дарии). Позволил арамейския език (днес познат като староарамейски) да е втори официален (освен персийския). Направил и ново разделение на империята на относително автономно управлявани 20 административни области. Вместо свои роднини, за техни управници назначил сътрудници от заверата си и други видни аристократи. Именно тези управници се наричали „сатрапи“, а областите съответно „сатрапии“.

Един от сатрапите бил именно Отанес. Под негово ръководство в областта се построили много пътища. Провел и множество военни походи, с които разширил границите на империята. Най-знаковата му победа като превождащ армията е била превземането на Византион (бъдещ Константинопол, днешен Истанбул).

А Дарий I, станал известен още като Дарий Велики, направил множество по-мащабни походи, като разширил империята към Египет и Гърция. Славната му военна кариера обаче приключва злощастно с голяма загуба при Битката за Маратон. След като неговият пълководец губи тази битка, той започва да подготвя нова офанзива, но здравословното му състояние се влошава и няколко години по-късно умира, без да успее да организира нов военен поход.

И като казах „Маратон“ - именно от тази битка произлиза понятието „маратонско бягане“. Атлетът Фидипид бил изпратен от град Маратон да търси помощ от армията в Атина, която се намира на 225 км. Той пробягал разстоянието без почивка за едно денонощие. Тази бърза реакция била ключова за бъдещата победа. По-късно в друг разказ на Плутарх се разказва, че същият Фидипид отново бил изпратен да тича от Маратон до Атина, но този път след битката, със задача да разкаже за победата. При второто бягане той обаче издъхнал от преумора и не успял да изпълни задачата.

П.П. Извън древногръцките приказки, съвремените историци смятат историята за Гаумата и отрязаните уши за невярна, а е по-скоро изфабрикувана от Дарий, за да оправдае завземането на властта. Най-вероятно цар Смердис си е бил истинския човек - брат на Камбиз II, - а данните за това, че е бил убит по нареждане на брат се не са били верни. Основанията за това са повече от логични - как единствено дъщерята на Отанес измежду всички в харема е разбрала, че това е друг човек и защо дъщерята на истинския Смердис - принцеса Пармис - не е казала никому нищо?

Ето как една интересна историческа приказка може да се превърне в урок по логика и логическо мислене, като така ще научи децата да отсяват историческите факти от художествените измислици. Смятам, че авторите на учебно съдържание по история трябва да помислят сериозно за един такъв подход в обучението.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Static в C/C++ 21 Mar 1:16 AM (7 months ago)

Ключовата дума static в C/C++ дава възможност на променлива да се запише в статичната област на паметта. Това е област, в която се дава възможност да се дефинират променливи с глобален обхват (в частност именно там се дефинират глобалните променливи). Те се намират в най-високите адреси на паметта, т.е. след heap. Или казано по друг начин - паметта изглежда по следния начин:

ниски адреси            високи адреси
STACK-расте-> | <-расте-HEAP | STATIC

Когато в C/C++ дефинираме глобална променлива, тя се разполага в STATIC паметта и се знае, че оттам насетне тя ще „живее“ там до края на изпълнението на програмата, както и че ще бъде споделена между всички функции.

Дефинирането на локална променлива като static ни дава възможност да я разположим в тази област и също „да живее“ до края на изпълнението на програмата, т.е. да не се загубва след края на изпълнението на функцията. Ще илюстрирам това с пример. Нека имаме функция, която дефинира локална променлива, увеличава я с единица и я отпечатва на екрана:

#include <stdio.h>
void func(){
   int counter = 0;
   counter++;
   printf("%d\n", counter);
}
int main() {
   func();
   func();
   func();
   return 0;
}

Съвсем очаквано резултатът ще са три пъти числото 1 на нов ред, защото всеки път се създава нова локална променлива counter (и тя „живее“ в стека при  всяко поредно извикване на функцията). Ако обаче направим counter да бъде статична локална променлива:

#include <stdio.h>
void func(){
   static int counter = 0;
   counter++;
   printf("%d\n", counter);
}
int main() {
   func();
   func();
   func();
   return 0;
}

резултатът вече ще е съвсем различен - вече ще получаваме числата 1, 2 и 3. При първото извикване на func() променливата counter се е създала в статичната памет и се е инициализирала на 0. При второто извикване тази променлива не се инициализира повторно (пропуска се "=0"), защото логиката е направена така, че това да се пропуска ако такава променлива вече съществува. Тоест при второто извикване на функцията вместо да се дефинира нова променлива counter с начална стойност 0, ще бъде използвана съществуващата в статичната памет променлива и ще се вземе нейната стойност, която е 1. Ето така локалните статични променливи дават възможност да си пазят стойността и след излизането от функцията.

Употребата на локални статични променливи в езика C е по-скоро непрепоръчителна. Обикновено те намират място в по-специфични случаи - например те са много удобни когато правим рекурсивни функции (когато една функция извиква самата себе си). Но дори при тях употребата на static е спорна. Ето един пример. Нека вземем класическата функция за пресмятане на числата на Фибоначи:

#include <stdio.h>
unsigned long long fibonacci(int n);
int main() {
   int n = 30;
   printf("Fib(%d) = %llu", n, fibonacci(n));
   return 0;
}
unsigned long long fibonacci(int n) {
   if (n > 93) return 0; // извън типа
   if (n <= 1) return n;
   return fibonacci(n-1) + fibonacci(n-2);
}

При много големи числа това пресмятане ще е изключително бавно. Затова можем да включим техниката, наречена „мемоизация“ - да си записваме вече изчислени числа в масив и да не ги пресмятаме пак. Вместо да е глобален (безсмислено, защото нямаме нужда от този масив извън самата функция) или пък да си го предаваме като входен параметър с указател, най-удобно е масивът да е статична за функцията променлива:

#include <stdio.h>
unsigned long long fibonacci(int n);
int main() {
   int n = 30;
   printf("Fib(%d) = %llu", n, fibonacci(n));
   return 0;
}
unsigned long long fibonacci(int n) {
   if (n > 93) return 0; // извън типа
   static unsigned long long memo[93] = {0};
   if (n <= 1) return n;
   if (memo[n] != 0) return memo[n];
   memo[n] = fibonacci(n-1) + fibonacci(n-2);
   return memo[n];
}

Извън рекурсивните алгоритми кодът става по-труден за проследяване и започва да крие неприятни „изненади“. Нещата се променят веднага когато се премине в света на обектно-ориентираното програмиране в C++. Там дефинирането на член-променлива на даден клас като статична веднага се явява като логична и често търсена техника за програмиране. Това прави член-променливата като споделен ресурс между всички обекти от съответния клас. Или да я приемем като глобална променлива за обхвата на класа. Чрез такива променливи например може различни нишки (Threads) да споделят общи ресурси. И т.н.

В света на ООП също получаваме и възможността да дефинираме статични функции. Това са функции, които могат да достъпват само и единствено статични член-променливи - ограничение, за сметка на което получаваме друго нещо, което е много удобно - такива функции могат да се извикват директно чрез името на класа, т.е. без да се създава обект. Именно така правим библиотеки с готови функции, които да се извикват директно, без да сме създавали обект с оператор new.

Но да се върнем обратно в света на C. Rма още един начин да използваме статични променливи - да дефинираме статични глобални променливи. Нека сравним следните два кода:

// код 1
#include <stdio.h>
int counter = 0;
void func(){
   counter++;
   printf("%d\n", counter);
}
int main() {
   func();
   func();
   func();
   return 0;
}

// код 2
#include <stdio.h>
static int counter = 0;
void func(){
   counter++;
   printf("%d\n", counter);
}
int main() {
   func();
   func();
   func();
   return 0;
}

Тук вече обхватът на променливата е глобален (тя е достъпна не само във функцията func(), а навсякъде в програмата). И двата  примера отпечатват 1, 2 и 3, т.е. видимо действат по един и същи начин. Къде тогава е разликата между тях?

Разликата се появява тогава, когато имаме връзки между различни фалове, т.е. когато един файл добавя код от друг. Нека разгледаме следния пример - създали сме проект в CodeBlocks, в който имаме един основен файл (main.c), един допълнителен (additional.c), който (според добрите практики) е вмъкнат не директно, а чрез посредничеството на header файл additional.h.

Нека се опитаме да дефинираме глобална променлива с едно и също име както в main.c, така и в additional.c. Ще видите, че няма да се получи. Съвсем логично компилаторът ще се оплаче и ще каже, че една и съща променлива се опитва да бъде декларирана два пъти. Ето примерния код:

// Основен файл: main.c
#include "additional.h"
#include <stdio.h>
int x = 5;
int main() {
   printf("main.c: %d\n", x);
   func();
   return 0;
}
// header файл: additional.h
#ifndef ADDITIONAL_H_
#define ADDITIONAL_H_
void func();
#endif

// втори файл: additional.c
#include "additional.h"
int x = 10;
void func(){
   printf("additional.c: %d\n", x);
}

Грешката тук ще бъде main.c|3|multiple definition of `x' и кодът няма да може да се компилира.

Ако искаме променливата да е една и съща и за двата файла (main.c и additional.c), трябва да я декларираме в единия от тях, а в другия да я маркираме като extern (външна за файла). Например така:

// Основен файл: main.c
#include "additional.h"
#include <stdio.h>
extern int x;
int main() {
   printf("main.c: %d\n", x);
   func();
return 0;
}
// header файл: additional.h
#ifndef ADDITIONAL_H_
#define ADDITIONAL_H_
void func();
#endif

// втори файл: additional.c
#include "additional.h"
int x = 10;
void func(){
   printf("additional.c: %d\n", x);
}

Дефинирайки променливата x като extern в main.c ние казваме на компилатора, че такава променлива ще има, но тя не е дефинирана в този файл. Бихме могли да направим тази декларация и в header файла - по този начин автоматично ще се включи в main и няма да имаме нужда от деклариране на extern променливите при всяко добавяне на библиотеката, която пишем. Независимо кой от двата подхода вземем, вече я няма грешката „повторно дефиниране“ (когато дефинираме две глобални променливи с едно и също име) или грешката с „няма такава променлива“ (когато се опитваме да ползваме променлива, която не е декларирана в текущия файл).

Да, но по този начин променливата x стана споделена между двата файла - променяйки я в единия ще се променя и в другия. Как да направим така, че main.c да си има своя собствена глобална (за файла) променлива x, а additional.c да има друга своя собствена глобална (за файла) променлива x? Именно тук се намесва ключовата дума static. Дефинирайки глобална променлива като статична ние променяме нейния обхват и той вече не е за цялата програма, а е само за текущия файл. Следният пример:

// Основен файл: main.c
#include "additional.h"
#include <stdio.h>
static int x = 5;
int main() {
   printf("main.c: %d\n", x);
   func();
return 0;
}
// header файл: additional.h
#ifndef ADDITIONAL_H_
#define ADDITIONAL_H_
void func();
#endif

// втори файл: additional.c
#include "additional.h"
static int x = 10;
void func(){
   printf("additional.c: %d\n", x);
}

ще даде следния резултат:

main.c: 5
additional.c: 10

Виждаме, че вече различните файлове си имат свои собствени статични глобални променливи и не се бъркат един с друг.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Кипчоге Кейно 25 Feb 9:23 PM (8 months ago)

Кипчоге Хезекая (Кип) Кейно е роден през 1940 г. в Кения. Като дете губи и двамата си родители и му се налага в общи линии да се оправя сам в живота.

Училището на Кип се е намирало на над 6 километра от дома му. Нямало училищни автобуси или какъвто и да е транспорт. През деня той изминавал това разстояние четири пъти - на отиване, връщане, и междинно прибиране до дома за обяд. Не просто го изминавал, а го бягал. Не просто го бягал, а го правил бос, защото нямал обувки... При това напомням, че в Кения по правило е ужасна жега. Това се повтаряло ежедневно години наред и започнало още по времето, в което бил едва на 5 годишна възраст.

Вече се досетихте, че човекът е станал много добър бегач на средни и дълги разстояния. Преди да попадне в света на спорта обаче работил известно време като полицай. Кения по онова време не е била толкова популярна държава с бегачите си по олимпийски игри, колкото е сега. Всъщност Кип е един от първите им звезди в бягането. Започнал го като нашега в свободното си време и изведнъж погълнало целия му живот.

Първото явяване на Кейно на олимпийски игри е в Токио през 1964 г. Не му достига малко, за да се класира на финала на 1500 метра. Година по-късно поставя световен рекорд на 1500 и на 5000 метра на състезание в Африка.

Големият му успех идва на олимпийските игри в Мексико през 1968 г. Интересен факт от тези игри е, че през цялото време Кип е страдал от болки заради камъни в жлъчката. Всъщност не успял да спечели първото си бягане на игрите - на 10 000 метра, - защото колабирал заради болки по време на състезанието (иначе само три обиколки преди финала той бил водач)... Бил дисквалифициран заради излизане извън пистата, но показал олимпийски дух, завърнал се и завършил обиколките си. Въпреки всички съвети на докторите да се откаже от по-нататъшно участие в игрите, защото има нужда от операция, той не се съгласил. Само два дни по-късно спечелил сребърен медал на 5000 метра.

Състезавал се на 1500 м. и също достигнал финалите. Болките на Кип се засилили и ден преди състезанието му се наложило да посети болница. Всички смятали, че това е краят и няма да може да отиде на състезанието. Лекарите му наредили да лежи в стаята на хотела си и да не се състезава въобще.

Час преди започването на финала, Кип станал от леглото си и се отправил към стадиона. За съжаление автобусът му попаднал в задръстване. Затова Кип слезнал от него и... изтичал около 8 километра по улиците, за да стигне до финала на състезанието...

На самото състезание пристигнал навреме и дори имал около 20 минути за почивка. Подготвил се, тичал, и... спечелил златен медал със забележително бягане.

Това не му стигнало и по-късно спечелил сребърен медал на състезанието на 3000 метра с препятствия.

На следващите олимпийски игри в Мюнхен 1972 г. взима сребро на 1500 метра. Стадионът в Елдорет (Кения) днес носи неговото име. Постоянен член на МОК е и разбира се е една от най-уважаваните личности в атлетиката.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Уве Хон – вечният шампион 6 Feb 8:59 PM (8 months ago)

Има един рекорд в хвърлянето на копие, който никога няма да бъде подобрен. Уве Хон (ГДР) е атлетът, който получава титлата „вечен шампион“ и променя този спорт завинаги!

Причината за това е, че е бил прекалено добър. Роден е през 1962 г. Започва да тренира спорта още като дете и в периода 1976 - 1980 г. е безапелационен шампион на ГДР при юношите. През 1981 г. става европейски шампион за юноши със световен рекорд. Година по-късно става европейски шампион и при възрастните играчи на състезание в Атина.

Не участва на световното първенство през 1983 г. и на олимпиадата през 1984 г., защото ГДР бойкотира игрите. По време на летните олимпийски игри обаче играе на паралелно състезание и поставя знаменит световен рекорд - цели 104,80 м. За сравнение, олимпийският шампион по това време е победил „само“ с 86,76 м.

Хвърлянето на Уве Хон тогава е наложило промяна в стандартите на играта. Олимпийските стадиони са проектирани така, че секторът за хвърляне на копие да е ограничен до 100 метра дължина на хвърлянето, защото се е смятало, че не могат да бъдат преминати. Хон за първи и единствен път прекрачва тази граница. Това естествено поставя на дневен ред въпросът за безопасността. Започнали са да търсят две възможни решения - да се удължи сектора или да се променят копията. Надделял е аргументът, че често е имало спорни съдийски отсъждания заради паднали хоризонтално копия, от IAAF са решили да предприемат второто.

Решението е било да се измести центъра на тежестта на копието с 4 см. напред, да се намали съпротивлението в предната му част и да се увеличи съпротивлението в задната му част. По този начин копията са спрели да падат хоризонтално и са започнали да падат по-близо спрямо преди. Поради тази причина световният рекорд на Уве Хон остава недостижим и последен със стария стандарт на копията. След нововъведението от април 1986 г. започва ново броене за рекордите. До този момент 100 м. продължават да са недостижими за друг атлет - световният рекорд на легендарния Ян Железни от 1996 г. е 98,48 метра.

През 1985 г. Уве Хон печели отново световна и после европейска титла (с европейски рекорд). През 1986 г. получава контузия, заради която се налага да приключи състезателната си кариера. Чак през 1999 г. се ориентира към треньорска кариера. В годините няма много сериозни успехи в международен план, но успява да подготви един шампион на Китай. Чак през 2017 г. сключва договор с индийската федерация, с която започва подготовката на младата надежда Нийрадж Чопра, който през 2020 г. става олимпийски шампион в Токио.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Антарктида 22 Jan 4:22 AM (9 months ago)

В България терминът Антарктида обикновено се свързва с проф. Пимпирев, експедиции и научни изследвания. Разбирането обикновено е, че тази слабо изследвана територия е необитаема и се използва само за научни бази. Зловещи условия, в които могат да оцелеят само най-добре подготвени хора със скъпа екипировка, нали? Континента обаче си има цивилно население! Не само това, но има и... местно население - хора, които са се родили там!

Официално първото бебе, което се е родило в Антарктика (не континента, а областта с прилежащите му води и острови), е момиченцето Солвейг Гунбьорг Якобсен (през 1913 г.), но то реално е родено при китоловната база на остров Южна Джорджия, която е меко казано далеч от самия континент Антарктида. Затова ще пропусна неговата история.

Исторически апетити към Антарктида всъщност не са били много. Първи териториални претенции прави Франция в първата половина на 19 век, а Великобритания, Нова Зеландия и Австралия се появяват там чак в началото на 20-ти. Изненадващо през 1940 г. се появява Норвегия, а за кратко и Германия с т.нар. „Нова Швабия“. Експедициите на норвежци и германци в крайна сметка отварят очите на двете държави, които се намират най-близко до континента - Чили и Аржентина. Опасявайки се, че ще изпуснат някоя златна възможност и ще загубят ценна земя под носа си, те използват размирното време на Втората Световна Война и съответно правят свои собствени експедиции, с които също правят териториални претенции за земи на континента.

Както може да се досетите, не закъсняват и конфликтите между изредените държави. Великобритания се е чувствала собственик на земите, които двете южноамерикански държави „завземат“ и това нямало как да мине без показване на мускули. Основна ябълка на раздора била най-близката до Южна Америка част от континента - тя е що годе еднакво близко до Чили, Аржентина и до Фолклендските острови, които Великобритания смятала за свои. Именно близостта прави тази част от Антарктида апетитна хапка. Напрежението растяло, а дипломацията не вървяла добре. В крайна сметка никоя от страните нямала силен коз в ръката си. Аржентина решила да поправи това и да си изфабрикува такъв.

В края на 1977 г. диктаторът Хорхе Видела изпраща капитан Хорхе Палма с експедиция от военни, за да направят база на континента. С въпросната експедиция капитанът закарва и своята бременна жена Силвия. Така на 7 януари 1978 г. се ражда Емилио Палма - първото бебе, което е родено на самия континент Антарктида. Заедно с тази експедиция заминават още седем цивилни семейства, чиято цел била именно да създадат местно население от „антарктици“ и по този начин Аржентина да предяви претенции към целия континент.

Отговорът на Великобритания не закъснял. Разбира се не основно заради бебето в Антарктида, а предимно заради другите териториални спорове, през 1982 г. избухва кратката Фолкландската война, в която Аржентина е разгромена.

Отговорът на Августо Пиночет от страна на Чили се забавя, но в крайна сметка те също правят местен жител на 21 ноември 1984 г. - Хуан Пабло Камачо. Тяхната тактика обаче била още по-развита - те не просто изпратили семейства с жени, които да родят там, но решили да направят така, че заселилите се семейства да заченат децата си на ледения континент.

В крайна сметка 11 бебета са родени на Антарктида през тези години - осем аржентинчета и три чилийчета. Така установените от двете държави бази и до ден днешен са единствените, в които живее цивилно местно население. В базите има училища, а чилийската дори си прилича на малко градче - има мобилна мрежа за телефони и интернет, офис на мобилния оператор, клон на банка, и др. В други бази на континента също има някакви форми на училища, а в руска база дори има черква, но само Чили и Аржентина могат да се похвалят с наистина местно антарктическо население.

Е, това местно население не успява да трогне и накара другите държави да признаят каквито и да е територии. Антарктида все още продължава да се счита за международна територия и никой не е признал владението на земя на друг. Съществува един крехък документ наречен "Antarctic Treaty System", в който в общи линии всички замесени с дейност на континента са се съгласили да не се развива никаква военна дейност, да няма добив на полезни изкопаеми и да няма замърсяване, за да може хабитатът там да се съхрани в максимално автентичен вид. Документът обаче не урежда териториални претенции, а такива кога гласно, кога негласно все пак има.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Рене Игита 6 Jan 9:10 AM (9 months ago)

Все се спори кой е по-велик - Меси, Роналдо, Мбапе, Холанд... Много малко са футболистите в историята, които са били толкова впечатляващи, че заради тях са били променяни правилата на самата игра. Дори Пеле и Марадона не са го правили! А един такъв футболист, който може би изобщо не помните, е Рене Игита.
Роден е 1966 г. Имал е много трудно детство. Баща му напуска семейството, а после майка му умира. Така е отгледан от баба си.

Още в първият си сезон като професионален футболист с колумбийския Мийонариос, като вратар изиграва 16 мача, в които... вкарва 7 гола! Изпълнявал преките свободни удари и дузпите, откъдето идват и вкараните голове. Но не с това бил забележителен. Станал емблематичен като първият вратар, който си позволява да поеме топката от своето наказателно поле, да дриблира до центъра на терена и чак тогава да подаде на свой съотборник в нападението. Така подемал изненадващи и ефективни контраатаки. Понякога стигал чак до противниковото наказателно поле. Много бързо станал популярен с тези си изпълнения, както и с атрактивните си спасявания. Много често правил нарочно акробатични скокове при хващането на топката, въпреки че като цяло тя е била лесна и не се е налагало. Било е много приятно шоу за публиката. А външният му вид - дълга къдрава коса и мустаци - го направили лесно разпознаваем медиен образ и така бързо се превърнал в сензация.

На световното първенство през 1990 г. му лепнали прякора „el Loco“ (лудият), защото отборът му загубил на 16-финал заради негово излизане и неуспешен дрибъл. Но това не го променило ни най-малко. Никой не му се сърдил и това не е накарало треньорите му да се опитват да го ограничават. Напротив - той и Карлос Валдерама се превърнали в иконите на колумбийския футбол, защото отборът никога не е бил достигал подобна фаза от турнира. Всъщност дотогава са се били класирали за първенството само ведъж и то през далечната 1962 г.

Международният фурор, който Игита прави с шоуто си на терена, стартира и инициатива за една доста важна промяна в правилата на футбола. Дотогава е било изключително честа практика защитниците да връщат топката на вратаря, а той да я улавя с ръце. Така да се внасяло спокойствие при защитаващия се отбор. Тактиката не само, че отнема от динамиката на футбола и прави т.нар. „преса“ неефективна, но също така е похват, с който може много да се бави играта. Това не е било проблем допреди средата на 80-те години, защото дотогава като цяло се е държало на поне някакъв морал и съответно фейърплей (не, че не е имало епизодични изцепки). Но комерсиализацията от 80-те променя това и всеки отбор иска да спечели на всяка цена. Започва да се злоупотребява с правилата и се достига до драстични примери. Например на същия мондиал 1990 г. вратарят Паки Бонър от Ирландия държал топката цели 6 минути и никой нищо не можел да му направи, защото не е имало предвидени наказания за бавене на играта. Естествено това е краен случай и не е било честа практика. Но връщането на топката започнало да става толкова често използван похват в практически всеки мач, че направило футбола буквално скучен. Повеждаш в резултата и после играеш на подавания между защитници и вратар. Нещо трябвало да се направи!

Игита бил единствения вратар, който изобщо не използвал тази тактика. Когато му връщали топката, той изобщо не я докосвал с ръце. Напротив - дори да е трудна и силна, той правил всичко възможно да я подхване с крак, след което дриблирал нападателите на противника и подемал контраатака. Това толкова много се харесвало на публиката, че едни от най-гледаните мачове на това световно били именно на Колумбия. Всичко било шоу с много динамика! Именно затова ФИФА решава, че може да вземе примера на Игита и да го превърне в правило. Първоначално обмисляли вариант, в който въобще да е забранено да се връща към вратаря, но това щяло да породи други проблеми. Примерът на Игита бил решението! Така за световното през 1994 г., на което за съжаление Игита не взима участие, е въведено правилото вратаря да няма право да хваща топката ако тя е върната от негов съотборник. Това коренно променя футбола по целия свят.

А Игита не взима участие на световното в САЩ, заради замесването му с колумбийската мафия, заради което влиза в затвора за 7 месеца. Наркокартелът на Пабло Ескобар отвлякъл дъщерята на друг наркобос - Карлос Молина, - а Игита действал като посредник за откупа. Това само по себе си не е укоримо и не е невероятно да го е направил с добри намерения, т.е. да не е бил замесен в самото отвличане. Но поради това, че е приел да получи лична награда от 64 хиляди долара за посредничеството от бащата на отвлеченото момиче, е бил осъден - нарушава закона. Световното през 1994 г. също става печално известно за Колумбия и с друга случка - убийството на защитника Андрес Ескобар от шофьора на наркобоса Сантяго Галон. Причината била, че Ескобар вкарал автогол на мача със САЩ, поради който отборът му губи и отпада от турнира, а Галон бил заложил огромна сума пари за победа на Колумбия.

Може би последната срамна сцена с връщане на топката към вратаря се случва на Евро 1992. Във финалния мач Дания повежда на Германия рано, а през 78-та минута удвоява резултата. В оставащите 12 минути се разиграва пълно фиаско, в което датчаните просто подават безконечно топката обратно до вратаря, а той им я връща обратно. Така не дават на Германия да направи нито една смислена атака. Чашата прелива и забраната вратаря да хваща с ръце върната от съотборник топка се превръща в повсеместно правило.

Друг забележителен момент в кариерата на Игита е по време на контролата между Колумбия и Англия на Уембли през 1995 г. Тогава той спасява гол с т.нар. „удар на скорпиона“. Скача и избива топката с петите на краката зад гърба си. Това спасяване го прави отново известен по цял свят, като често се показва по медиите като пример за нестандартна игра и до днес.

Последващата кариера на Игита е в различни отбори на Латинска Америка. Играе чак до 43-годишна възраст! Завършва кариерата си с 41 гола за клубни отбори и 3 гола за националния отбор. Това го прави петият по голове вратар в света. Първи е бразилецът Рожерио Сени с цели 131, втори е Хосе Чилаверт с 62 (единственият вратар с хеттрик), трети е Хорхе Кампос с 46, четвърти е Джони Фернандес с 45 и веднага след него е Игита с неговите 44. Шести пък е българинът Димитър Иванков с 42.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Бети Лу Оливър 4 Jan 8:26 PM (9 months ago)

На 28 юли 1945 г. заблуден бомбандировач B-25 се врязва в 79-ти етаж на Емпайър стейт билдинг в Ню Йорк. В сградата зейнала дупка с диаметър около 6 метра. Имало голям пожар. Освен пилота, на място загиват още 14 души, които са били на етажа в сградата.

Бети Лу Оливър тогава е била на 20 години и е работила като оператор на асансьор. Намирала се е на 80-ти етаж и претърпяла изгаряния по тялото заради пожара. Дошлия екип за спешна помощ ѝ помогнал да се свести, след което я качили в друг товарен асансьор сама, за да се евакуира.

Тогава се случил втори инцидент. Въжетата се скъсали някъде около 75-ти етаж и асансьорът полетял надолу в свободно падане. И оцеляла! В интервю след инцидента заявила, че летенето било толкова бързо, че трябвало да се запречи с ръце и крака в краищата на кабината, за да не полети... нагоре... Отървала се само със счупен таз и два прешлена - един при гръбнака и вратен.

След продължително лечение успяла да се възстанови. Още в първия ден в болницата дала интервю пред медиите. Доживява си старините и почива от старост през 1999 г.

А Емпайър стейт билдинг отново отваря врати, забележете, само 48 часа по-късно! Дупката не била оправена, но останалата част на сградата си функционирала на пълни обороти още в понеделник.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Мадам Чинг – най-влиятелният пират в историята 4 Jan 8:16 PM (9 months ago)

Мадам Чинг (Ching Shih) е била най-влиятелният пират познат на човечеството. Първоначално е била проститутка. Известен пират се влюбил в нея и се оженили. Постепенно той ѝ дал командването на част своята "мафия" и тя започнала да я развива. Била толкова успешна, че още в първите 6 години утроили флотилията си от кораби от 200 на 600.

Когато мъжът ѝ умира в буря, тя поема цялото командване на създадената организация. Разрастването продължило и в един момент имала 1800 кораба и между 70 и 80 хиляди пирата под свое командване. Организацията си имала свои закони (повечето наказания са били смъртни) и основната дейност била рекет на търговски организации. На няколко пъти е влизала в пряк военен конфликт с флотите на Китай, Великобритания, Португалия и Холандия, и винаги е печелила безапелационно всички битки, като пленявала много кораби.

В крайна сметка императора на Китай решил, че ще се справи с проблема, но и сметнал, че разходите ще са прекалено голями. Затова ѝ предложил пълна амнистия срещу разформироване на флота, но с право да се задържи всичко, което е било придобито от тях. Неочаквано за всички тя приела. Вторият ѝ мъж придобил чин във флота на Китай, а тя придобила аристократична титла и се оттеглила от морските дела. Мадам Чинг умира на 69 годишна възраст като управител на оргомен игрален (и публичен) дом.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Карлос Рапозо – футболистът, който не е изиграл нито един футболен мач 21 Dec 2024 9:20 PM (10 months ago)

Роден в Бразилия, като младеж Карлос получил прякор Кайзера заради марката бира, която предпочитал да пие. Човекът имал добри физически показатели и бил доста силен, но нямал добри умения да играе футбол. Мечтата му обаче била, цитирам: да стана футболист, но без да играя футбол.

Самият той бил обаятелен като личност. Затова започнал да се върти в средите, където се събират футболисти. Оказало се, че прякорът му доста помагал, защото тогава изключително популярния футболист Франц Бекенбауер имал същия. И така завързал сериозни приятелства с известни личности като Карлос Торес, Рикардо Роча и Ренато Гаучо. Именно те го препоръчали и бил нает да играе в мексиканския отбор Пуебла. Тактиката, която изградил там, започнал да прилага и в бъдеще при всеки следващ отбор:

  1. Подписва нарочно кратък едногодишен договор и отказва дългосрочни ангажименти;
  2. Първите няколко седмици твърди, че има проблеми с физическата подготовка, поради което основно се занимава с натоварващи упражнения за тялото, където е силен и успява да впечатли треньорите;
  3. Когато започне тренировка с останалите, симулира контузия с разтягане на подколянното сухожилие - тогавашните технологии не са можели да го изследват и потвърдят, поради което лекарите просто го приемали на доверие;
  4. Когато от клуба започвали да мрънкат и да се усъмняват, той използвал връзки с близък негов зъболекар, който декларирал тежка инфекция. Друг път използвал мобилни телефони-играчки, с които симулирал разговори на чужд език пред треньори и съотборници, за да покаже, че е търсен за трансфер в чужбина и съответно за известно време изчезвал. И правил куп други подобни неща, с които да отложи колкото се може по-дълго изхвърлянето му от клуба;
  5. Накрая придумвал мениджърите, че е по-добре да го продадат другаде, за да имат поне някаква полза от него.

Завръщайки се в Бразилия през 1979 г., накарал негови приятели-журналисти да напишат възхваляващи качествата му статии. Измислили история как бил поканен да получи мексикански паспорт, за да постъпи в националния им отбор. Това, заедно с връзките му с известни футболисти, го уредило директно с трансфер в известния клуб Бутафого. Приложил гореописаната тактика и успял да се задържи повече от година. Издал се говорейки по мобилния телефон имитирайки английски език, защото докторът на клуба говорил перфектен английски и като чул нелепите глупости, които говори, естествено се усъмнил.

Кариерата му не свършила дотам. Мениджърите на Бутафого не искали да останат прецакани и набързо уредили Кайзера с трансфер във Фламенго през 1981 г. Там историята с фалшивата контузия се повторила - имитирал травма за няколко месеца и живеел живот на футболист, но само извън терена. От Фламенго така и не успели да го разконспирират, въпреки че не изиграл нито един мач (не попаднал в състава дори като резерва). Обаче успели да го рекламират много добре пред известния аржентински мениджър Хорхе Буручага и го продали на Атлетико Тарелес, откъдето бил преотстъпен бързо в Индепендиенте.

След скромен и срамен престой в Аржентина, през 1985 г. се завърнал обратно в Бразилия, но този път сравнително по-скромния клуб Бангу. Там решил, че е време да украси биографията си и започнал да разправя как с Индепендиенте през 1984 г. е спечелил Копа Либертадорес и Интерконтиненталната купа в мач срещу Ливърпул. Всичко било изключително достоверно, защото в Индепендиенте по онова време е имало млад играч с име Карлос Енрике - само, че Карлос Алберто Енрике, който по-късно става национал на Аржентина и печели Копа Америка през 1991 г. Имената се изписвали леко различно (Henrique за нашия герой и Enrique за онзи, за който се представя), но това се приемало като просто разлика в езиците между двете страни. Историята му била достоверно изглеждаща!

Фалшивите контузии продължили. Успял да НЕ изиграе нито един мач, но се уредил с трансфер в Европа във втородивизионния френски отбор Газелек Аячо, където играел негов приятел и бил препоръчан. Там за нещастие му спретнали изненада - тренировъчна сесия за представяне пред феновете. Той нямало как да впечатли никого с футболни качества и затова решил да направи шоу - взел голяма значка на клуба и започнал да рита една по една топки в публиката, като всеки път целувал значката. Това се харесало на феновете и те започнали да го аплодират.

Но... така и не играл за отбора. Всъщност бил хванат бързо в измама и сам се върнал обратно в Бразилия, където буквално се укривал няколко месеца, за да не разбере никой, че не е във Франция. Предвидливо обаче си бил направил доста снимки с екипа на клуба, които му били сериозно доказателство, че е играел сериозно там. След време решил да е крайно нагъл - накарал приятел-журналист да напише статия, в която се казва как Карлос Кайзера е бил топ голмайстор на френския клуб!

Кой мислите, че го е наел през 1987 г. след тази история? Добрият стар клуб Фламенго! Естествено се „контузил“ и колелото се завъртяло. Тогава набързо го продали през 1988 г... отново в Бангу. И отново се „контузил“. След което започнал възстановителни тренировки... и така се подготвял за нов трансфер. Тогава обаче случило и нещо опасно за Кайзера - мениджърът на клуба се ядосал, че го гледа само да тренира, и изведнъж решил: възстановяващ се, не възстановяващ се, ще го вкара като резерва в един мач. Отборът за нещастие губел с 0:2 и... мениджърът на клуба наредил на треньора да вкара Карлос в игра.

Мислите, че е играл ли? Ами не. Още преди да влезе на терена той налетял на бой и започнал да обижда фен от трибуните. Съдията моментално му показал червен картон... След мача обяснил, че фена го е напсувал и го е нарекъл „крадец“. Това спасило кожата му и успял да се задържи още цели шест месеца в клуба! Естествено в крайна сметка вбесил всички и го продали на нов отбор - Флуминезе.

Историята на Кайзера във Флуминезе завършва повече от срамно за него през 1989 г. Отново имитирайки разговори с английски агенти, един от помощник-треньорите го разкрива. Този път няма трансфер и затваряне на очи в името на парите - направо го изхвърлят от отбора и му прекратяват договора.

Никакво отказване! Същата година е нает от известния отбор Вашку Да Гама, но не за да играе (от там явно вече са знаели, че е футболист-менте), а с изричното условие да помогне на негов приятел, който бил много добър футболист, но имал проблеми с алкохола. Кайзера не пиел и имал репутация на много достоен човек. И определено бил обаятелен и вдъхновяващ като приятел! Това проработило - свършил си работата много прилично, за което от клуба били доволни. За награда му уредили трансфер и излъгали отбора от САЩ Ел Пасо Сиксшутърс. Постоял в щатите няколко месеца и набързо се усетили, след което го трансферирали обратно в Бразилия в Америка-RJ.

Кариерата на Карлос Кайзера завършва изключително неочаквано за всички. Той се урежда в трансфер в... Бутафого!!! Да, онзи отбор, който в началото на кариерата му открива измамата му. Новото ръководство явно не са проверили достатъчно добре досието му и не са разбрали, че вече е „играл“ при тях. След няколкомесечен престой, Карлос решава през 1992 г., че е време да се откаже от футболната си кариера на 29-годишна възраст. Нападателят приключва с футбола с 0 гола и нито едно излизане на терена. След време признава публично за всичките си измами.

През 2016 г. излиза филма „Кайзер! Най-добрият футболист, който никога не е играл футбол“. През 2018 г. със същото заглавие излиза и книга. Ако футболът е цар на спортовете, то Карлос Кайзера определено е цар на измамите във футбола.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Цената на високите успехи: образованието в Южна Корея 17 Dec 2024 9:04 PM (10 months ago)

Всички знаете за това колко високи постижения постигат азиатските държави по международни ученически състезания. А знаете ли каква е цената, която се плаща зад това?

През 70-те години на миналия век публичното образованието в Южна Корея (една от топ 10 държавите по PISA днес) е било на доста занемарено ниво. По-амбициозните родители били крайно разочаровани от държавно-финансираните училища, но обучението в тях било задължително. Така започнала масова практика за „доучване“ с частни уроци. Родителите започнали масово да записват децата си на частни школи, които работели след нормалния учебен ден. Повечето били т.нар. „вечерни училища“ - такива, които работят от 18 до 21-22 часа. Представете си как едно дете започва училище в 8 сутринта, учи в общинското училище целодневно до към 16-17, след което преминава към частно училище за още 3-4 часа, където да доучва. Реално режимът му е учи-спи-учи-спи... Това разбира се не се е случвало през целия период на училищно образование. Концентрацията на учене в такъв режим се фокусира предимно при класовете, след които има важни изпити, свързани с кандидатстване (еквивалент на нашите НВО и матури). Но имало и явна тенденция към разрастване. Все повече ставали примерите за хора, които записват децата си на школи още от първи клас.

През 80-те години на миналия век в Южна Корея е започнала образователна реформа. Основната ѝ идея е, че трябва да се намали въпросното частно образование и да се даде по-голямо равенство между класите. Основанието било, че по-богатите семейства могат да осигурят сравнително лесно скъпите вечерни училища за децата си, но има бедни хора, които не могат. По този начин се създава класово разделение, което според политиците било лошо за обществото.

Реформата нямала нищо общо с повишаване на качеството на общественото образование. Първоначално се опитали да забранят вечерните училища. Повечето от тях продължили да работят нелегално. Засилването на контрола и увеличаването на санкциите само изместило фокусът от школите към още по-скъпите частни уроци. Борбата на държавата с нелегалните частни уроци явно била обречена.

Стигнало се до нова идея - да се въведат безплатни обществени вечерни училища за всички ученици, които желаят. Основанието било, че щом държавата не може да забрани частното образование, тя ще започне да го конкурира. Създали концепцията за „вечерно самообучение“. То давало свободен достъп за всеки ученик до сградата на общинско или държавно училище през вечерно време, където децата да могат да си пишат домашните работи под надзора на дежурни учители.

Идеята за използване на взаимообучителен метод (учениците да си помагат едни на други) постепенно се е изродила в традиционна „занималня“. И вероятно точно така е било заложено. Получил се просто по-дълъг учебен ден за почти всички деца в държавата. Постепенно над 1900 от общо 2258 училища предложили не само допълнително безплатно обучение до 20-21 часа (някои дори до 23:00!), но дори и т.нар. „нулев час“ (по желание на родителите учебния ден започвал със „сутрешен час за самоподготовка“). В някои по-крайни случаи се оказвало, че децата стоят всеки ден на училище от 7 часа сутринта до 23 часа вечерта!

Създадената система за учене извън времевия интервал от 8 до 16 часа не е задължителна. Практиката обаче показва, че който не се възползва от допълнителните часове, изостава. Така постепенно повечето ученици в Южна Корея реално са принудени да учат 5-6 допълнителни часа всеки ден. Безплатното образование като цяло продължава да не е на високо световно ниво, което може да се потвърди поради факта, че частните вечерни училища и частните уроци изобщо не са изчезнали, а продължават да са си масова практика (оборотът им е общо над 20 милиарда щатски долара годишно). Количествените натрупвания на допълнителни часове за учене все пак в крайна сметка си казват думата. Южна Корея в днешни дни е традиционно в челните места при международни класации за постижения в образованието. На каква цена обаче се случва това...

Значението на състезателния елемент в образованието в Южна Корея може да илюстрира с примера, че там има т.нар. „учители-суперзвезди“. Това са много известни хора, които дават частни уроци само за децата на най-богатите хора. Такъв например е Ким Ки-хуун, който е учител по английски език и стана популярен по света като учителят, който е заработил 4 милиона щатски долара от частни уроци онлайн през 2013 г.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Гранада – Барбадос (1994) 13 Dec 2024 10:35 PM (10 months ago)

Най-лудият футболен мач в историята: Гранада - Барбадос (1994). Предисторията започва от тогавашните правила на турнира за Карибската купа. Въпреки че в групите не е имало директни елиминации, всеки мач се е изисквало да завърши с победител. Тоест при равенство е имало продължения и евентуално дузпи. Традиционно за времето е имало и т.нар. „златен гол“ - ако се отбележи попадение по време на продълженията, мачът приключва. Това сте го виждали и на Световното първенство по футбол преди. Но в Карибската купа златният гол е бил различен - той се е броял не за един, а за два гола! Ако например мач завърши в редовното време 0:0 и домакините вкарат златен гол, в ранг листата ще се запише победа с 2:0. И накрая - ако два отбора в класирането са с равни точки, напред продължава този с по-добра голова разлика.

Текущото състояние на групата е било следното:

  1. Гренада, 3 точки, 1 победа, 0 загуби, голова разлика +2
  2. Пуерто Рико, 3 точки, 1 победа, 1 загуба, голова разлика -1
  3. Барбадос, 0 точки, 0 победи, 1 загуба, голова разлика -1

Достигаме до 27 януари 1994 г., когато се играе последния мач от групата - Барбадос срещу Гренада. Гостите от Гренада са очевидно в по-добра позиция - равен мач или победа очевидно ги прави победители в групата. Хубавото за тях е, че ще бъдат първи в групата дори и при загуба, но не с повече от 1 гол разлика. Единственият начин да не продължат напред в турнира е да загубят с 2 или повече гола - тогава Барбадос ще ги изпревари. Пуерто Рико разбира се нямат никакъв шанс при какъвто и да е резултат. Тоест въпросният мач е бил решаващ и за двата отбора.

Мачът започнал рутинно, като домакините имали преимущество през цялото време. Още през първото полувреме вкарали два бързи гола и се оттеглили в защита. Задържали аванса си... до 83 минута. Тогава се случило нещо неприятно за тях - Гренада върнали един гол и резултатът станал 2:1.

Барбадос трябвало спешно да вкарат гол и опитали. В следващите три минути атакували масирано, но честно казано не се виждал изглед как ще пробият вече буквално глухата защита на опонентите си. Вече била 86-та минута и мачът приключвал. И тогава им хрумнала интересна идея: да си вкарат автогол! Барбадос се досетили, че ако мача стане равен, ще влезнат в продължения и така ще имат много повече време да атакуват за евентуален златен гол, който ще им даде не един, а два гола разлика и по този начин ще спечелят групата!

Защитникът Тери Сийли и вратарят Хорас Строут си подавали топката за минутка един на друг и накрая полевият играч вкарал демонстративен автогол в 87-та минута. Доволни, че вкарват мачът в продължения, от Барбадос започнали да се радват на изравняването на резултата.

От Гранада обаче мигновено разгадали плана на съперника и не били доволни. Били топката от центъра и тръгнали да атакуват. И тогава от своя страна се досетили за интересен феномен - дали ще успеят да вкарат гол на противника или автогол на самите себе си, това ще е все победа. Наистина - дали ще спечелят или ще загубят с един гол разлика все ги класира напред. От Барбадос усетили какво ще последва и техния отбор бързо се разделил на две... и започнали да пазят и двете врати!

Следващите 3 минути били наистина комични - един отбор се опитва да вкара на друг в която и да е от двете врати. Избрали по-лесното - да вкарат в своята собствена, защото там няма чужд вратар, а техния може да хване топката и просто да я хвърли в мрежата. Колкото и да звучи парадоксално обаче - не успяли! От Барбадос им отнели топката и успели да я задържат около центъра на терена до изтичане на редовното време.

Мачът влезнал в продължения и за черешка на тортата - познахте, Тревор Торн от Барбадос успял да вкара златен гол, с което изкачил отборът си на първо място в групата. В края на мача треньорът на Гранада Джеймс Кларксън бил бесен и направил следното изказване пред камерите:

- Чувствам се измамен! Този, който е измислил тези правила трябва да влезне в лудницата. Футболът не трябва да се играе с толкова много играчи, които тичат объркани в различни посоки. Нашите футболисти дори не знаеха в коя посока да атакуват - към собствената или към чуждата врата. Не съм виждал подобно нещо преди. Във футбола трябва да вкараш на противника, за да победиш, а не да вкарваш на себе си!

Но почакайте, има и още един случай!

Разбира се след този турнир „двоен златен гол“ не се е прилагал никога повече. Всъщност правилото за златен гол по-късно отпада напълно, защото става честа практика в продълженията отборите да не се атакуват един-друг поради страх от контраатака.

Този проблем обаче все още не е напълно изчезнал от футбола. Ставали сме свидетели как в групова фаза на турнири два отбора нарочно играят пасивно, защото резултатът ги устройва и заедно се класират напред. Виждали сме и как един отбор видимо губи тенденциозно, за да може да се падне с по-лесен противник.

Може би най-яркият пример, който може да бъде даден, е мачът между PSS Sleman и PSIS Semarang от Индонезия през 2014 г. По време на плейофите и двата отбора са щели да се класират независимо от резултата. Получило се така обаче, че загубилият мача е щял да играе срещу Pusamania Borneo F.C.. По принцип се считало, че Борнео е отбор със силен гръб от мафията и съответно техните мачове са уредени за да станат шампиони. Затова никой от двата отбора не искал да играе с тях.

Целият мач протекъл вяло и никой не нападал - било ужасяваща скука от безсмислени подавания. И така в последните четири минути започнала фиеста от... автоголове. По-точно цели пет на брой! Слиман „спечелили“ с 3:2, но след сериозно бавене на топката и усилия от страна на противника да им попречат да си вкарат автогол... Заради това фиаско, футболната асоциация на Индонезия наказала с дисквалификация и двата отбора.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Някои популярни алгоритми за сортиране, реализирани на Java 5 Dec 2024 11:42 PM (10 months ago)

Кодът по-долу представя основни алгоритми за сортирани. Реализацията им е на Java. Правени са в учебна среда - възможно е да има допуснати неточности и грешки.

static void selectionSort(int[] arr) {
  int min_index;
  for (int i = 0; i < arr.length - 1; i++) {
   min_index = i;
   for (int j = i + 1; j < arr.length; j++) {
    if (arr[j] < arr[min_index]) {
     min_index = j;
    }
   }
   int temp = arr[i];
   arr[i] = arr[min_index];
   arr[min_index] = temp;
  }
}

static void bubbleSortUnoptimized(int arr[]) {
  for (int i = 0; i < arr.length - 1; i++) {
   for (int j = 0; j < arr.length - i - 1; j++) {
    if (arr[j] > arr[j + 1]) {
     int temp = arr[j];
     arr[j] = arr[j + 1];
     arr[j + 1] = temp;
    }
   }
  }
}

static void bubbleSort(int arr[]) {
  boolean swapDone;
  for (int i = 0; i < arr.length - 1; i++) {
   swapDone = false;
   for (int j = 0; j < arr.length - i - 1; j++) {
    if (arr[j] > arr[j + 1]) {
     int temp = arr[j];
     arr[j] = arr[j + 1];
     arr[j + 1] = temp;
     swapDone = true;
    }
   }
   if (swapDone == false) {
    return;
   }
  }
}

static void mergeSort(int[] arr) {
  if (arr.length < 2) {
   return;
  }
  int mid = arr.length / 2;
  int[] leftPart = new int[mid];
  int[] rightPart = new int[arr.length - mid];

  for (int i = 0; i < mid; i++) {
   leftPart[i] = arr[i];
  }
  for (int i = mid; i < arr.length; i++) {
   rightPart[i - mid] = arr[i];
  }
  mergeSort(leftPart);
  mergeSort(rightPart);

  int i = 0, j = 0, k = 0;
  while (i < mid && j < arr.length - mid) {
   if (leftPart[i] <= rightPart[j]) {
    arr[k] = leftPart[i];
    k++;
    i++;
   } else {
    arr[k] = rightPart[j];
    k++;
    j++;
   }
  }
  while (i < mid) {
   arr[k] = leftPart[i];
   k++;
   i++;
  }
  while (j < arr.length - mid) {
   arr[k] = rightPart[j];
   k++;
   j++;
  }
}

static void quickSort(int[] array) {
  class LocalClass {

   void quickSortRec(int[] arr, int lowIndex, int highIndex) {
    if (lowIndex >= highIndex) {
     return;
    }
    int pivotIndex = new java.util.Random().nextInt(highIndex - lowIndex) + lowIndex;
    int pivot = array[pivotIndex];
    int temp = array[pivotIndex];
    array[pivotIndex] = array[highIndex];
    array[highIndex] = temp;

    int leftPointer = lowIndex;
    int rightPointer = highIndex - 1;

    while (leftPointer < rightPointer) {
     while (array[leftPointer] <= pivot && leftPointer < rightPointer) {
      leftPointer++;
     }
     while (array[rightPointer] >= pivot && leftPointer < rightPointer) {
      rightPointer--;
     }
     temp = array[leftPointer];
     array[leftPointer] = array[rightPointer];
     array[rightPointer] = temp;
    }

    if (array[leftPointer] > array[highIndex]) {
     temp = array[leftPointer];
     array[leftPointer] = array[highIndex];
     array[highIndex] = temp;
    } else {
     leftPointer = highIndex;
    }

    quickSortRec(array, lowIndex, leftPointer - 1);
    quickSortRec(array, leftPointer + 1, highIndex);
   }
  }
  new LocalClass().quickSortRec(array, 0, array.length - 1);
}

static void insertionSort(int arr[]) {
  for (int i = 1; i < arr.length; i++) {
   int temp = arr[i];
   int j;
   for (j = i - 1; j >= 0 && arr[j] > temp; j--) {
    arr[j + 1] = arr[j];
   }
   arr[j + 1] = temp;
  }
}

static void countSort(int arr[]) {
  int max = arr[0];
  for (int i = 1; i < arr.length; i++) {
   if (arr[i] > max) {
    max = arr[i];
   }
  }
  
  int[] countingArr = new int[max + 1];
  for (int i = 0; i < arr.length; i++) {
   countingArr[arr[i]]++;
  }
  for (int i = 1; i <= max; i++) {
   countingArr[i] += countingArr[i - 1];
  }

  int[] sortedArr = new int[arr.length + 1];
  for (int i = arr.length - 1; i >= 0; i--) {
   sortedArr[countingArr[arr[i]] - 1] = arr[i];
   countingArr[arr[i]]--;
  }

  System.arraycopy(sortedArr, 0, arr, 0, arr.length);
}
 
static void ranksSort(int[] arr){
  int[] ranks = new int[arr.length];
  for(int i=0; i<arr.length; i++){
   int i_rank = 0;
   int dups = 0;
   for(int j=0; j<arr.length; j++){
    if(arr[i]>arr[j]){
     i_rank++;
    }
    else if(arr[i] == arr[j] && i!=j){
     dups++;
    }
   }
   for(int k=0; k<=dups; k++, i_rank++){
    ranks[i_rank] = arr[i];
   }
  }
  System.arraycopy(ranks, 0, arr, 0, arr.length);
}

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

За проблемите около понятието квадратен корен 21 Nov 2024 9:21 PM (11 months ago)

Понятието квадратен корен е объркващо за децата в училище. Основният проблем е в неразбирането на знака за радикала: √. Много често (почти винаги!) се прави грешката когато се види √ да се каже квадратен корен от.... А това всъщност не е така.

Знакът √ всъщност означава неотрицателния квадратен корен. Тоест би трябвало да се знае уж добре познатото и преповтаряно многократно правило: [mathi]\sqrt{{x}^2} = |x|[/mathi]. Често обаче не го изричаме по този начин и това естествено обърква учениците. Друга грешка, която правим много често, е че пропускаме стъпки, т.е. пишем например [mathi]\sqrt{4} = 2[/mathi] вместо [mathi]\sqrt{4} = |2| = 2[/mathi]. Така неволно скриваме важна характеристика на знака на радикала, която би трябвало да акцентираме.

Нека вземем следния пример: трябва да се реши [mathi]{x}^2 = 16[/mathi]. Често прибързано казваме на децата коренуваме двете страни на равенството и записваме на дъската следното:

[math]{x}^2 = 16 \implies \sqrt{{x}^2} = \sqrt{16} \implies x= \pm 4[/math]

Крайният отговор тук е верен, но междинната стъпка не е. Логичният въпрос, който децата ще си зададат веднага, е защо тогава [mathi]\sqrt{16} = 4[/mathi], а не [mathi]\sqrt{16} = \pm 4[/mathi]? А отляво защо имаме [mathi]\sqrt{{x}^2} = x[/mathi], а не [mathi]\sqrt{{x}^2} = \pm x[/mathi]. Не се вижда логика и това нерядко води до объркване и пропуски.

Записът не е неверен, защото са пропуснати стъпки, а именно: [mathi]|x|=|4| \implies |x|=4[/mathi], от където следва и отговорът [mathi]x = ±4[/mathi]. Уточняването на това обстоятелство обаче не разрешава проблема, че продължава да има неразбиране за разликата между понятието за квадратен корен и знака √. Така само се замазва положението, а не се разрешава фундаменталния проблем.

Всичко това може да бъде поправено ако поне в началните часове, когато казваме коренуваме двете страни на равенството, изписваме подробно цялостния запис на решението на задачата. Той е следния:

[math]\begin{align*} & \sqrt{{x}^2} = 16 \implies \pm \sqrt{{x}^2} = \pm \sqrt{16} \implies \sqrt{{x}^2} = \pm 16 \\ & \implies |x| = \pm \sqrt{16} \implies x = \pm \sqrt{16} \implies x = \pm |4| \implies x = \pm 4 \end{align*}[/math]

Връзката между второто и третото равенство е, че премахваме дублиращите се две комбинации измежду четирите възможни. Същото се случва и при четвъртото и петото: [mathi]\pm (\pm \sqrt{16}  ) = \pm \sqrt{16}[/mathi]. Усетихте ли най-важния момент? Думите коренуваме двете страни на равенството не са еквивалентни на поставянето на знака на радикала √ отляво и отдясно. Трябва да се постави ±√ от двете страни на равенството!

Обобщение. Когато преподавате се опитвайте да изричате термините зад математическата символика по правилен начин. В конкретния пример те са следните.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Какво е меден месец? 13 Nov 2024 8:48 PM (11 months ago)

Всички знаете какво е меден месец. А знаете ли откъде произлиза?

Основната теория за възникването на тази фраза е свързана с краденето на булки. Това е практика, която се е случвала при почти всички народи - когато бащата не разрешава даден брак, младежите бягат (момчето „открадва“ момичето) и се опитват момичето да забременее. Когато не ѝ дойде месечния цикъл, момчето връща дъщерята обратно и поставят бащата пред свършен факт - той вече няма как да откаже сватбата.

Отделно от това традиционно през вековете се се считало, че пиенето на алкохолното питие медовина помага силно за повишаване на потентността и често се е предписвала като „лекарство“ за безплодие. И ето как двете неща се навързват - младежът краде девойката и в рамките на един месец пият много медовина, за да могат да си направят дете. А когато някой неосведомен се почуди защо ги няма тези конкретни младежи, обяснявали му че са „на меден месец“.

Един от първите писмени записи с употребата на тази фраза, е от Ричард Хюлоет (английски лексиграф) през 1552 г. Той пише, че терминът „Hony mone“ се използвал вулгарно за описание на това, което ще се случи с всички младоженци - до една фаза на Луната любовта им угасва. Тук може да се усети и препратката към евентуалния произход на фразата: зад нея наистина не е стояла някаква добре приета практика, а напротив - свързвали са я с нещо лошо.

При всички случаи „меден месец“ не е имало нищо общо с пътувания и ваканция. Практиката с туризма се случва чак в началото на 19. век във Великобритания. Там започнал да се практикува „bridal tour“ (булчински тур) от богатите хора в аристокрацията и била свързана с обиколка на младоженците до свои роднини в провинцията, които не са успели да посетят тяхната сватба. Французите бързо започнали да копират тази практика като „voyage à la façon anglaise“ (пътуване по английски), откъдето практиката се разпространила и в континентална Европа.

Чак в края на 19. век хората от по-бедни слоеве на населението започнали да копират практиката за едномесечна обиколка по провинцията. Така искали да подражават на аристократите. Повечето от тях обаче нямали чак толкова много свои роднини по далечни места и за тях всичко се изродило в обикновена туристическа обиколка, имитираща посещения на измислени роднини. Като подигравка към такива псевдоаристократи-имитатори, по-богатите започнали да им се присмиват с препратка към „меден месец“ в смисъла от миналото, т.е. за да ги обиждат, че техния туризъм е сходен с криенето по пещерите и по горите при крадене на булки. Но понеже фразата звучи сладичко и приятно - постепенно тя е изгубила смисъла си и станала това, което знаем за нея днес.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Историята на Фолксваген 1 Aug 2024 11:33 AM (last year)

Фердинанд Порше създава Фолксваген. Десетилетия по-късно компанията Порше купува над 50% акции на Фолксваген. След това пък Фолксваген купува 100% от автомобилния бизнес на  Порше. В крайна сметка се оказва, че Порше притежава Фолксваген, а Фолксваген притежава Порше. Объркващо е, нали? Цялата история е по-долу...

Автомобилният гигант Фолксваген е създаден през 1937 г. като изцяло държавна компания. Известният и произвеждан чак до 2013 г. модел „костенурка“ тогава е разработен от Фердиданд Порше, бъдещ създател на известната марка автомобили Порше. До онзи момент той имал собствена компания на негово име (създадена 1931 г.), но не е произвеждал свои автомобили, а е бил само подизпълнител и консултант при дизайн на такива.

Личната компания на Порше не му е била приоритет. Първият проектиран под негова марка автомобил е модел 64 и е направен през 1939 г. във фабрика в Щутгарт. Колата обаче била произведена само в три броя. Като дизайн, двигател и много от компонентите си той бил много подобен на „констенурката“ и това не било случайно - личната фабрика на Порше била много тясно свързана с по-големия производител Фолксваген. Самият Фердинанд Порше участвал пряко в управлението на държавната компания. Заради войната основният му фокус бил във Фолксваген, която освен автомобили се занимавала и с производство за военни нужди.

След края на Втората световна война Фердинанд Порше изгубил поста си във Фолксваген. Британците поели пълен контрол над управлението и го изгонили. Тогава той започнал да лобира пред френското правителство фабриките на Фолксваген да се преместят във Франция (под формата на компенсации заради войната) и така той да продължи да управлява компанията. Това било много примамливо за френското правителство, но идеята се сблъскала с отпор от назначения управител на Рено. Тогава последният официален собственик Луис Рено бил вкаран в затвора заради колаборация с германците и умрял при неизяснени обстоятелства, а компанията била национализирана, а новият управител на Рено, който бил индустриалец и герой от войната, виждал в преместването на Фолксваген във Франция огромна заплаха за управляваните от него заводи. Така той лобирал от своя страна пред властите и се стигнало до завеждане на дело, от което в крайна сметка осъдили Порше като военопрестъпник заради това, че в заводите на Фолксваген са работили роби. Вкарали го в затвора и с това проектът Фолксваген да стане френска компания умрял, а Федерална република Германия (ФРГ) останали собственици на фабриките, управлявани под временен контрол от британската армия.

Докато баща му е в затвора, синът му Фери Порше решава да разработи и да се опита да произведе собствен автомобил през семейната фирма. Не произвежда нищо, но разработката му все пак била много обещаваща. С това успява да съхрани жива компанията на баща си и тя да остане активна до освобождаването му от затвора през 1947 г. След излизането на Фердинанд на свобода, с вече разработения и готов за производство модел 356, той се залавя за производство, но не в Щутгарт, а в Австрия. Моделът става много успешен и с това се поставя началото на славната компания за производство на спортни автомобили.

През 1949 г. Фердинанд Порше и семейството му се преместват да живеят обратно в Германия и възраждат фабриките в Щутгарт. До края на живота си Фердинанд Порше имал апетит отново да поеме контрол над Фолксваген, защото е чувствал компанията до някаква степен негова. Това обаче вече нямало как да се случи. През ноември 1950 г. се опитал да осъществи контакт с вече немските директори на Фолксваген и да ги накара да направят съвместен бизнес около много популярните „негови“ костенурки, но само няколко седмици по-късно получил сърдечен удар. Не успял да се възстанови и по-късно починал, с което тази идея за колаборация се провалила. Компанията Порше поела в своя собствена посока и връзката с Фолксваген се скъсала напълно.

През 1960 г. наследникът на Фолксваген - правителството на ФРГ - решава да извърши приватизация на компанията и да я предаде в частни ръце. Компанията обаче била „прекалено голяма, за да умре“ и затова политиците решават да измислят специален протекционистки закон, с който държавата да задържи контрол над предприятието и да не позволи то да бъде унищожено от външни сили. Така се гласува специален „Фолксваген закон“, според който наличието на повече от 20% акции имат блокиращ глас над всяко решение, а правителството на Долна Саксония имало гарантирани 20,2% от тях. С това ФРГ реално задържало контролната си роля над предприятието, но го предало за управление при частници. Най-различни фондове инвестирали в компанията и управлението станало шарено.

При тази приватизационна сделка Порше не участват съществено. Първата нова колаборация между компаниите се осъществява чак през 1969 г., когато Фолксваген правят два спортни автомобили с двигатели на Порше. По-късно, през 1976 г. Порше правят два свои модела, в които използват много части произведени от Ауди (собственост на Фолксваген), но като цяло това е относително малка допирна точка между двата производителя на автомобили. Пътищата им се преплитат по-късно по по-особен начин.

В този период през 1972 г. Порше се преструктурира от семейна компания в AG, защото бизнесът нарастнал прекалено много. Опасенията били, че няма да се справят с управлението в тесния семеен кръг. Преструктурирането включвало изпълнителен борд на директори да е от хора извън фамилията, а членовете на фамилията да участват само в контролен борд. Този фирмен дизайн бил изкопиран от Хонда. Несъгласен с това компанията напуска Фердинанд Пиех, който е внук на Фердиданд Порше. Тогава той решава да поеме по собствен път и отива да работи за Ауди.

Пиех прави много успешна кариера и реализира много популярни модели в Ауди - например Quattro и 100. Така бавно, но сигурно се издига до изпълнителен директор на Фолксваген през 1993 г. С това може да се каже, че един наследник на Порше е успял да превземе създадената от дядо му компания, но отвътре. Под негово ръководство чак до 2015 г. Фолксваген се издига още повече, с което става огромният автомобилен гигант, който познаваме и до днес. Но това не е краят на историята. Именно под негов контрол се получава така, че компанията на семейството му Порше дефакто става и формален собственик на Фолксваген. Но как?

През 1993 г., точно когато Пиех поема управлението на Фолксваген, се сформира Европейски Съюз. С това вече обединена Германия трябва да реформира своето законодателство. В частност е засегнат и законът за Фолксваген, който вече не можел да съществува заради изискването за свободно движение на капитали. Германия обаче настоятелно отказвала да го отмени.

Първото дело в Европейският съд срещу Германия заради закона за Фолксваген завършва чак през 2007 г. Решението било въпросният закон да бъде отменен. Междувременно по време на управлението на Пиех съмнително Porsche SE започнали все по-усилено да купуват акции на Фолксваген. Правителството съзирало в това голяма опасност. Когато Европейският съд приключил делото, Porsche SE, собственик на компанията за производство на автомобили Porsche AG, вече притежавали цели 30,9% от акциите на Фолксваген. Германия се притеснявала, че именно те ще пожелаят да станат мажоритарен собственик на Фолксваген със закопуването (вече нужните) само над 50% акции.

Германското правителство тогава се опитало да се изхитри и вместо да отмени, само да промени закона и така само частично да отпусне регулацията, с което да замаже очите на Европейската комисия. Отменили само частта, която гарантира 20,2% от акциите на Долна Саксония, но в същото време задържали регулацията, която дава 20%+ гарантирано вето над всяко решение. С това те имитирали отмяна на протекционизма - уж позволяват Долна Саксония да продаде акции и така да изгуби ветото си, но... тя явно никога нямало да го направи, защото би било много непопулярна мярка.

Европейската комисия разбира се моментално завела ново дело. Междувременно Porsche SE продължили да купуват още и още акции, като до януари 2009 г. достигнали заветните 50,76%. В този момент се оказало така, че ако Европейският съд отсъди, че новият закон трябва да падне, тогава със сигурност е щяло Porsche SE да стане мажоритарен собственик на Фолксваген и да може да се разпорежда по-свободно със съдбата му.

Делото обаче не било леко и се забавило. А Porsche SE трябвало да инвестират огромни суми в закупуването на акциите. Потънали в дългове, които не можели да изплащат и се принудили да поемат по пътя на продажба на своя основен бизнес - за продажба на автомобили, т.е. да продадат Porsche AG. И тук познайте кой е купил компанията... С активно въздействие на Пиех, това били Фолксваген груп! Първоначално купили 49,9%, а по-късно придобили 100% от компанията.

Така се получила една много интересна спойка: компанията-майка на Порше притежавала Фолксваген (макар и блокирана от германското правителство), а Фолксваген притежавали основният бизнес на Порше. Това било, така да се каже, мъртва хватка между двете компании. Те вече не можели да съществуват една без друга!

Това положение продължило до 2013 г., когато Германия била отново принудена от съда да промени закона, така че да отговаря на европейските правила. По-съществено правото на вето с 20% било отменено и така Porsche SE получили пълен контрол над компанията. С това пък дефакто си върнали и контролът над производството на собствените им автомобили.
Ето така наследниците на Фердинанд Порше успели в крайна сметка да върнат контрола над създадената от него компания.

Бонус факт: в град Вратиславице над Ниш в родният дом на Фердинанд Порше, който станал собственост на Шкода, през 2011 г. е създадена експозиция на коли на компанията. След двугодишни протести на оцелели от Холокоста, от местният общински съвет са принудени през 2013 г. да поставят на улицата табелки, в които да се упомене, че Фердинанд Порше е бил член на нацистката партия и член на СС. Това ядосва собствениците на Порше и те изтеглят автомобилите от музея. Той продължава да съществува и до днес, но в доста по-скромен вид.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Пенго: най-голямата хиперинфлация в историята 25 Jul 2024 10:08 PM (last year)

Инфлацията в Унгария през 1945/1946 г. е най-голямата в човешката история. За да разберете за какво става дума, още в началото ще споделя историческите данни от Уикипедия за курс на пенгото към щатския долар:

Предистория.

След загубата на Първата световна война (ПСВ), Австроунгарската империя се разпада и Унгария става самостоятелна държава. Тогава приемат нова валута - корона, която е наследник на австроунгарската корона. Липсата на техника и средства на централната банка ги принуждава да изработят банкнотите с изключително евтин печат на слабозащитена хартия. Това прави фалшифицирането на короната изключително лесно, а от там може да се досетите, че инфлацията избухва.

Ако преди ПСВ австроунгарската корона устойчиво се е обменяла по курс около 5 за 1 щатски долар, до 1924 г. курсът за новата унгарска корона е достигнал до около 70 хиляди за 1 щатски долар. Въпреки последвала кратка стабилизация, става ясно, че не може да се продължава така и короната трябва да отиде в историята.

Въвеждането на пенго.

На 1 януари 1927 г. Унгария премахва от обръщение старата корона и въвежда нова валута - пенго. Обменният курс към този момент е бил 12500 корони за 1 пенго. Опитали са се да имитират, че пенгото е обвързано със златен стандарт, като са записали официално отношение на пенго към килограм злато, но това не е било реално, защото златото се продавало по съвсем други курсове (първоначално само като микс 50:50 с друга валута и то 1/5 от официалния грамаж за същите пари). По-нататък валутата се стабилизира и до 1930 г. пенгото успява да покрие златния си стандарт, а след това става една от най-устойчивите валути в Европа. Така останало до започването на Втората световна война (ВСВ), когато заради войната инфлацията започнала бавно, но сигурно да расте.

Икономическият колапс от ВСВ и нарастващата хиперинфлация.

В периода между 1940 и 1945 г. Унгария претърпява тежък разгром на икономиката. До края на войната около 90% от индустрията на държавата е унищожена, а от там икономиката изпада в тежка криза. Пенгото започнало да се обезценява, но поради военното положение всичко било по-особено и курсът му често бил удържан изкуствено. Например с репресии от страна на военните търговците били принуждавани да фиксират цените си и така инфлацията някак била удържана. Затова реалната инфлация не била ясно видима във военната обстановка. Оценките са били, че пенгото се обезценило няколко десетки пъти спрямо щатския долар (не, че някой ги е омбенял тогава), но това не е било нищо спрямо това, което щяло да последва.

Хиперинфлацията на Унгария в периода 1944-1946 г.

Представяте ли си да се събудите и да установите, че имате почти два пъти по-малко пари днес, отколкото сте имали вчера? Точно това се е случвало в пика на хиперинфлацията.

След като войната за Унгария приключва, икономиката е в тотален колапс и проблемите с валутата ескалират. За определени периоди цените на стоките започнали да се се удвояват в рамките на половин ден! Така последователно се появяват мерните единици милпенго (милион пенго) и бързо след това билпенго (трилион пенго). На 11 юли 1946 г. е отпечатана последната банкнота от 100 милиона билпенго (това е 100 квинтилиона пенго). И даже тя не била най-голяма от всички. Бил подготвен проект за банкнота от 1 милиард билпенго (еквивалентна на 1 секстилион пенго или единица с 21 нули пенго) и такива са били дори отпечатани като мостри, но не се е стигнало до въвеждането им в обръщение. Не е имало банкнота с по-голям номинал в историята на човечеството.

Така между 1945 и 1946 г. парите в Унгария практически не са имали никакво значение. От 1 януари до 30 юли 1946 г. е циркулирала и алтернативна валута, наречена адопенго (пенго за данъци), която е имала особен статут и не е можела да се ползва свободно от гражданите - била е само за държавни дела и междубанкови операции. Чак в последния месец е имало и свободно нейно обръщение. Тя също е страдала от хиперинфлация, но по-слабо спрямо обикновеното пенго.

Съветската армия, която е окупирала държавата, също е напечатала свои собствени военновременни пари, които също са били закратко в обръщение. Последните пенго монети са били пуснати през 1945 г. и са били алуминиеви. След това не е имало никакъв смисъл да съществуват.

Какво се случва след юли 1946 г.

Валутите пенго и адопенго престават да съществуват и за са сменени от форинта. На 1 август 1946 г. той е въведен официално по курс 1 форинт за 4×10^29 пенго, т.е. премахване на 29 нули и делене на 4. Към адопенгото курсът е бил 1 форинт за 200 милиона. Обвързали го със злато по курс 1 килограм за 13210 форинта, което бързо стабилизирало валутата. Така форинта останал устойчив за следващите две десетилетия. После постепенно започнал да пропада. През 90-те успява да се стабилизира, но от 2008 г. насам е с устойчива тенденция за срив спрямо еврото и долара (намалил е стойността си два пъти).

Бонус факт. Голям проблем в първата и втората година от въвеждането на форинта е бил липсата на хартия. Печатането на пенго преди това е било изчерпило всички налични хартиени ресурси на държавата. Затова трябвало да внасят хартия от чужбина.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Double submit cookie 14 May 2024 3:39 AM (last year)

Техниката за двойно изпращане на бисквитка се използва за превенция на XSRF атаки в случаите, в които не желаем да записваме XSRF token в сесията или просто не използваме сесии.

Идеята е да запишем xsrf token в клиентско cookie. После този token ще се вмъкне в скрито поле в HTML формата, която трябва да бъде защитена. При приемането на резултата ще се прави проверка дали записаното в бисквитката съвпада с подаденото през формата. Защитата се корени в това, че ако хакерът накара клиента да отиде на някакъв негов уебсайт и да попълни автоматично форма, която изпраща данните към нашия, той не може да прочете бисквитките на клиента и съответно няма да знае какъв е записания token. Така въпреки, че с нашата заявка ние ще изпратим бисквитката с въпросния token, той няма да присъства в подадените от формата полета и съответно валидацията ще пропадне.

Нека започнем от пример с уязвима форма. Във файл form.php имаме следната уязвима на XSRF форма:

<!DOCTYPE html>
<html lang="bg_BG">
<head>
   <title>Форма, защитена с Double cookie submit</title>
   <meta charset="utf-8">
</head>
<body>
   <form action="form_destination.php" method="POST">
      <input type="text" name="message" />
      <input type="submit" name="submit" value="Изпрати" />
   </form>
</body>
</html>

А във form_destination.php следното:

<?php
   if(!isset($_POST['message'])){
      header("Location: form.php");
      exit;
   }
   echo htmlentities($_POST['message'], ENT_QUOTES, "utf-8");
?>

Най-простата форма на xsrf token за техниката double cookie submit е да генерираме случайно число с голяма ентропия и да го запишем в cookie при клиента. Това би могло да се случи с javascript (но в този случай httponly флага на бисквитката трябва да бъде изключен, а това я прави уязвима при евентуални XSS атаки). Друг вариант е преди достигането до страницата с формата (т.е. на предхождаща страница - например по време на login) да сме задали бисквитката по следния начин:

<?php
   $statelessXSRFToken = base64_encode(openssl_random_pseudo_bytes(32));
   setcookie("statelessXSRFToken", $statelessXSRFToken,
             ['expires'=>0, 'samesite'=>'Lax', 'httponly' => true, 'secure'=>true]);
?>

След като сме задали COOKIE, можем да използваме statelessXSRFToken, за да защитим нашата форма:

form.php:

<!DOCTYPE html>
<html lang="bg_BG">
<head>
   <title>Форма, защитена с Double cookie submit</title>
   <meta charset="utf-8">
</head>
<body>
   <form action="form_destination.php" method="POST">
      <input type="text" name="message" />
      <input type="hidden" name="statelessXSRFToken" 
             value="<?=$_COOKIE['statelessXSRFToken']?>" />
      <input type="submit" name="submit" value="Изпрати" />
</form>
</body>
</html>

Този начин на работа може да е неудобен, защото не можем да имаме форма, която е директно защитена - трябва първо да имаме страница, в която създаваме token и чак след това можем да отидем да използваме формата. Бихте могли да решите този проблем като генерирате различен token на всяка страница - това има сериозни предимства и от гледна точка на сигурността, но същевременно създава известни проблеми на потребителите (нови табове, бутона назад в браузъра, и т.н.). Повечето от тези проблеми са отстраними, но засега ще ги оставим на заден план и ще използваме следния код за удобство при тестовете:

form.php:

<?php
  // вместо това може да генерирате token през JavaScript, но тогава
  // ще трябва да задавате cookie с 'httponly'=>false, което го прави
  // уязвимо на потенциални XSS атаки
  $statelessXSRFToken = base64_encode(openssl_random_pseudo_bytes(32));
  setcookie("statelessXSRFToken", $statelessXSRFToken,  
            ['expires'=>0, 
             'samesite'=>'Lax', 
             'httponly'=>true, 
             'secure'=>true]);
?> 
<!DOCTYPE html> 
<html lang="bg_BG"> 
<head> 
   <title>Форма, защитена с Double cookie submit</title> 
   <meta charset="utf-8"> 
</head> 
<body> 
   <form action="form_destination.php" method="POST"> 
      <input type="text" name="message" /> 
      <input type="hidden" name="statelessXSRFToken" 
             value="<?=$statelessXSRFToken?>" /> 
      <input type="submit" name="submit" value="Изпрати" /> 
   </form> 
</body> 
</html>

form_destination.php:

<?php
   if(!isset($_POST['statelessXSRFToken'], $_POST['message'])){
      header("Location: form.php");
      exit;
   }
   if($_POST['statelessXSRFToken']!==$_COOKIE['statelessXSRFToken']){
      echo $_POST['statelessXSRFToken'];
      exit;
   }
   echo htmlentities($_POST['message'], ENT_QUOTES, "utf-8");
?>

Това е най-базовата възможна защита, позната още като наивна. По принцип не е препоръчителна.

Проблемът с фиксиране на XSRF token

Макар и много прост, този вариант на защита за съжаление има потенциален недостатък. Ако сайтът няма HSTS (уязвим е на SSLStrip атака) и хакерът има възможност на пренасочва и модифицира негови заявки (man in the middle атака), то би могло да бъде осъществен следния сценарий:

  1. Клиентът желае да отвори mywebsite.dom.
  2. Хакерът извършва SSLStrip и му изпраща фалшив отговор от сървъра, като кара клиента да запише cookie с измислен от него XSRF token.
  3. След това хакерът пренасочва клиента към своя страница, където е заложил форма, в която измисления от него XSRF token е попълен в скрито поле.
  4. Накрая кара браузъра на клиента автоматично да натисне бутона на мнимата форма.

Макар и с много условности, това е потенциална уязвимост, отстраняването на която не зависи от кода на приложението, а от администраторите на домейна (трябва да активират HSTS, за да няма SSLStrip).

За да гарантираме в кода, че XSRF token е издаден от нас, можем да направим следното (това все още не решава описания проблем):

form.php

<?php
   DEFINE("XSRF_KEY", "1NWNmvm2p8Iew&hxUtaoX5PHQTDoyslb");
   $statelessXSRFToken = base64_encode(openssl_random_pseudo_bytes(32));
   setcookie("statelessXSRFToken", 
             hash_hmac("sha256", $statelessXSRFToken, XSRF_KEY),
             ['expires'=>0,
              'samesite'=>'Lax',
              'httponly'=>true,
              'secure'=>true]);
?>
<!DOCTYPE html>
<html lang="bg_BG">
<head>
   <title>Форма, защитена с Double cookie submit</title>
   <meta charset="utf-8">
</head>
<body>
   <form action="form_destination.php" method="POST">
      <input type="text" name="message" />
      <input type="hidden" name="statelessXSRFToken" 
             value="<?=$statelessXSRFToken?>" />
      <input type="submit" name="submit" value="Изпрати" />
   </form>
</body>
</html>

form_destination.php:

<?php
   DEFINE("XSRF_KEY", "1NWNmvm2p8Iew&hxUtaoX5PHQTDoyslb");
   if(!isset($_POST['statelessXSRFToken'], $_POST['message'])){
      header("Location: form.php");
      exit;
   }
   if(hash_hmac("sha256", $_POST['statelessXSRFToken'], XSRF_KEY)!==$_COOKIE['statelessXSRFToken']){
      echo 'XSRF';
      exit;
   }
   echo htmlentities($_POST['message'], ENT_QUOTES, "utf-8");
?>

По този начин предотвратихме възможността хакера да фиксира генериран от самия него XSRF token, но все още сме уязвими. Например ако има SSLStrip (или пък XSS уязвимост и флагът 'httponly' за бисквитката е изключен, защото например желаем да сме по-гъвкави и да генерираме бисквитката динамично през JavaScript), хакерът ще може да ни накара отново да използваме негов фиксиран XSRF token, като направи следното:

  1. Да отиде на нашия уебсайт и да генерира валиден подписан XSRF token за самия себе си.
  2. Да използва SSLStrip или XSS уязвимостта и да ни накара да фиксираме в cookie неговия валиден XSRF token.
  3. Оттам да извърши XSRF атаката - той вече може да генерира своя форма, която ще премине през защитата.

Решението на този проблем е да вградим като част от ключа нещо, което е уникално за потребителя. Като минимум може да се извлекат някакви характеристики на браузъра на клиента, но това е несигурно, защото вероятно хакерът може да ги предскаже (ако не успее да ги извлече от нас). За съжаление опциите ни при stateless решения не са много.

Ако обаче използваме сесия (напр. системата е с вход с наш потребителски профил), можем да конкатенираме към ключа сесийното id, което е гарантирано уникално - тогава хакерът няма да може да ни накара да използваме неговия token, защото той няма да съвпада.

form.php:

<?php
   session_start();
   session_regenerate_id(true);
   DEFINE("XSRF_KEY", "1NWNmvm2p8Iew&hxUtaoX5PHQTDoyslb");
   $statelessXSRFToken = base64_encode(openssl_random_pseudo_bytes(32));
   setcookie("statelessXSRFToken", 
             hash_hmac("sha256", $statelessXSRFToken, XSRF_KEY.session_id()),
             ['expires'=>0,
             'samesite'=>'Lax',
             'httponly'=>true,
             'secure'=>true]);
?>
<!DOCTYPE html>
<html lang="bg_BG">
<head>
   <title>Форма, защитена с Double cookie submit</title>
<meta charset="utf-8">
</head>
<body>
   <form action="form_destination.php" method="POST">
      <input type="text" name="message" />
      <input type="hidden" name="statelessXSRFToken" 
             value="<?=$statelessXSRFToken?>" />
      <input type="submit" name="submit" value="Изпрати" />
   </form>
</body>
</html>

form_destination.php:

<?php
   session_start();
   DEFINE("XSRF_KEY", "1NWNmvm2p8Iew&hxUtaoX5PHQTDoyslb");
   if(!isset($_POST['statelessXSRFToken'], $_POST['message'])){
      header("Location: form.php");
      exit;
   }
   if(hash_hmac("sha256", $_POST['statelessXSRFToken'], XSRF_KEY.session_id())!==$_COOKIE['statelessXSRFToken']){
      echo 'XSRF';
      exit;
   }
   // променяме го след валидацията на XSRF
   session_regenerate_id(true);
   echo htmlentities($_POST['message'], ENT_QUOTES, "utf-8");
?>

С това решение проблемът е напълно решен, защото дори хакерът чрез XSS да открадне сесийното id, няма да може да генерира свой XSRF токен с него, който да фиксира (друг е въпроса, че открадването на сесийното id вероятно ще доведе до много по-тежки последици за потребителя и XSRF ще е проблем на много по-заден план).

Дали да се използва сесийно id е много спорно. Причината да използваме double cookie техниката вместо да вграждаме xsrf token генериран от страна на сървъра и записан в сесийна променлива е, че искахме защитата да е stateless. В случая добавяме сесия и правим отново всичко stateful...

П.П. За отстраняването на проблема с back бутона на браузъра или зареждането на страницата в отделен tab, може просто да се откажем да използваме различен token, а вместо това да е винаги един и същи (например да се задава еднократно при login). Това не се счита за сериозно намаляване на защитата при положение, че cookies са httponly (не могат да бъдат откраднати например през JavaScript при наличие на XSS уязвимост), както и ако сме се погрижили за BREACH. Но ако все пак искаме XSRF token да е различен на всяка страница, можем на направим следното:

Тази техника вече е коментирана в статията за XSRF. Ето примерно решение:

form.php:

<?php
   // Еднократно генерираме фиксиран XSRF token
   if(!isset($_COOKIE['fixedXSRFToken'])){
      $fixedXSRFToken = base64_encode(openssl_random_pseudo_bytes(32));
      setcookie("fixedXSRFToken", 
                $fixedXSRFToken,
                ['expires'=>0,
                 'samesite'=>'Lax',
                 'httponly'=>true,
                 'secure'=>true]);
   }
   else{
      $fixedXSRFToken = $_COOKIE['fixedXSRFToken'];
   }

   // Генерираме уникален token за текущата страница
   $dynamicXSRFToken = base64_encode(openssl_random_pseudo_bytes(32));
   // Подписваме го с фиксирания + уникален секрет от сорс кода
   // Тук е препоръчително към ключа да се добави уникална характеристика
   // за потребителя - например session_id, ако решим да използваме сесия
   DEFINE("XSRF_KEY", "1NWNmvm2p8Iew&hxUtaoX5PHQTDoyslb");
   $signedXSRFToken = hash_hmac("sha256", 
                                $dynamicXSRFToken, 
                                $fixedXSRFToken.XSRF_KEY);
?>
<!DOCTYPE html>
<html lang="bg_BG">
<head>
   <title>Форма, защитена с Double cookie submit</title>
   <meta charset="utf-8">
</head>
<body>
   <form action="form_destination.php" method="POST">
      <input type="text" name="message" />
      <input type="hidden" name="dynamicXSRFToken" 
             value="<?=$dynamicXSRFToken?>" />
      <input type="hidden" name="signedXSRFToken" 
             value="<?=$signedXSRFToken?>" />
      <input type="submit" name="submit" value="Изпрати" />
   </form>
</body>
</html>

form_destination.php:

<?php
   DEFINE("XSRF_KEY", "1NWNmvm2p8Iew&hxUtaoX5PHQTDoyslb");
   if(!isset($_COOKIE['fixedXSRFToken'], $_POST['dynamicXSRFToken'], $_POST['signedXSRFToken'], $_POST['message'])){
      header("Location: form.php");
      exit;
   }
   if(hash_hmac("sha256", $_POST['dynamicXSRFToken'], $_COOKIE['fixedXSRFToken'].XSRF_KEY)!==$_POST['signedXSRFToken']){
      echo 'XSRF';
      exit;
   }
   echo htmlentities($_POST['message'], ENT_QUOTES, "utf-8");
?>

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Из историята на текстовия редактор vi 13 May 2024 2:56 AM (last year)

Първият в света What you see is what you get (WYSIWYG) текстови редактор е създаден преди близо 50 години. Казвал се е Bravo и е бил предназначен за Xerox Alto. Всяка буква от клавиатурата е съответствала на команда. Писането на текст се извършвало с команда "i" (insert) - отваря буфер, който се запълва до натискане на бутона Return. Най-проблемно за новаците било да седнат, да отворят документ и да напишат думата "edit". Команда "e" (everything) маркирала целия текст, "d" (delete) го изтривала, "i" (insert) вкарвала в режим за писане и "t" просто вкарвал буквата t. За нещастие команда "u" (undo) можела да обърне само последната операция.

Идеята всеки бутон да отговаря на определена команда е дошла заради прекалено бавните модеми, с които терминалите работели. Трябвало да се спести колкото се може повече мрежови трафик и затова най-удачно било всяка команда да е просто единичен символ.

Днес части от Bravo продължават да живеят на повечето компютри по света. Създателят на визуалната надстройка vi на редактора ex (който от своя страна е производен от по-старите en, ed и em) е признал в интервю, че по-голямата част част от идеите за vi са били буквално изкопирани от Bravo. Вече са минали 45 години, откакто vi е включен официално като част от операционната система 2BSD. Думата "vi" всъщност е синоним на команда "visual", която вкарва ex във „визуален режим“. Програмата vi в Linux/BSD всъщност пуска ex (версия 2.0) директно в такъв режим. Може да пробвате сами. Затова по същество е неправилно да се казва, че vi е текстови редактор - редакторът всъщност се казва ex.

А чудили ли сте защо буквите h, j, k и l във vi действат по същия начин като бутоните със стрелки (местят курсора наляво, надолу, нагоре и надясно)? Причината е, че на клавиатурата за терминала ADM-3A, който разработчикът е използвал, не е имало отделни бутони за стрелки, а бутоните с тези букви са имали двойна функция.

За времето си ex е била изключително тежка програма. Заемала е почти цялата оперативна памет на повечето машини, на които е била използвана. При версия 3.1 дори се разширила толкова, че някои терминали вече не можели да го ползват! А днес ex вероятно е най-лекият текстови редактор.

Създателят на vi Бил Джой през декември 1978 г. е работил върху възможност за създаване на „прозорци“, т.е. да могат да се отварят много документи на един екран. За негово нещастие устройството за резервни копия (магнитна лента) се било развалило. Въпреки това той продължил да работи няколко седмици поред. Бил в много напреднала фаза, когато се случила бедата - повреда в компютъра му и така загубил всичко. Това го ядосало изключително много и тогава решил да зареже проекта - оставил го на свои колеги да го продължат. Днес всички Linux/BSD системи включват в себе си модифицирани варианти (клонинги) на редактора (напр. при FreeBSD се използва nvi, а в Linux се използва vim).

Накрая не може да не се завърши с кратка информация за битката за надмощие при текстовите редактори между EMACS и vi. Създават се и две пародийни религии - Църквата на Emacs и Култът на vi. Покрай тях се нарояват и множество вицове. Например:

It's difficult to get out of the vi mindset once you've^]Bdwiyou're in it.

Казва се също, че първата стъпка в кариерата на един хакер е да успее да излезе от vi, без да си повреди документа. Или пък: във vi има два режима - постоянно писукане и повреждане на всичко. Също: ако пуснете незапознат потребител да поработи с vi, ще получите псевдослучаен генератор на поредици от букви. И т.н. Обратно - за Emacs има редица закачки свързани с името: Escape Meta Alt Control Shift, Eight Megabytes And Constantly Swapping, EMACS Makes Any Computer Slow, Eventually Munches All Computer Storage, и др. Или пък предизвикателство за EMACS: задръж CTRL или ALT и си напиши името...

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Плаващите училища в Бангладеш 28 Mar 2024 10:17 PM (last year)

В Бангладеш около 20% от територията на страната страда от тежки наводнения по време на мусоните. Говорим за период от началото на месец юни до средата и понякога дори до края на октомври. В по-критични ситуации понякога се стига и до над 70% потопена територия. Бедствията от наводненията по това време на годината са много чести.
Можете да си представите колко тежко е за живот на хората от такива райони. Очаквано те не строят масивни постройки, които могат да бъдат унищожени ако се потопят под вода, а по-скоро живеят в леки колиби, които могат лесно да бъдат възстановени за кратко време. А какво се случва с училищата?

Логично и очаквано, те масово не работят в периода, в който са потопени под вода. Понякога дори училището да успее да отвори, много деца все още не могат да достигнат до него, защото пътищата са непроходими. Това води до сериозно изоставане на децата от наводнените региони и те трудно наваксват с учебния материал спрямо останалите връсници. Много от тях отпадат от училище и остават неграмотни.

Този проблем привлича международното внимание. Създава се фондацията Шидхулай Сванирвар Сангстха, която се включва с набиране на средства, за да подкрепи тези деца. Тръгват с идеята, че ако децата не могат да отидат до училището, училището ще отиде при децата.

През 2002 г. за първи път се показва концепцията с първата училищна лодка. Постепенно се формират цели 20 плаващи училища (всяко с по няколко лодки). Говорим за плавателни съдове със соларни панели на покривите, в които могат да се обучават до 30 ученици. Някои от тях са оборудвани с традиционни чинове, дъска за писане от страна на учителите и имат лаптоп с проектор, а други са направени като спортни площадки с различни уреди за тренировка (доколкото се може функционални физкултурни салони). Лодките са буквално с функция 2 в 1 - те са не само училище, но сами и училищен "автобус", защото минават по къщите и сами събират децата.

Всяко училище предоставя обучение само от I-ви до V-ти клас. Учи се интензивно между два и три часа на ден през шест дни в седмицата. Обучението е на смени - дневна и вечерна, като вечерната е основно за децата, на които през деня се налага да работят, за да се изхранват семействата си. Освен основната грамотност - да четат и пишат - обучението е фокусирано предимно върху прагматични за ежедневния живот в тези райони знания, като например как да се пречиства питейна вода, ефективно отглеждане на различни земеделски култури, и др. Понякога към такива обучения се привличат и възрастни хора.

След часовете на децата се раздават книги и учебни материали, с които да могат да учат вкъщи. Понеже често им се налага да пишат домашните си вечерно и нощно време, а същевременно нямат никакво електричество, от училището им осигуряват и фенери с презареждаеми батерии, за ги използват като нощна лампа. Най-дорите ученици получават такива фенери със слънчев панел за зареждане на батериите като подарък във вид на стипендия.

До 2015 г. през програмата са преминали обучение 70000 ученици. Към днешен ден вероятно вече са над 100000.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Покриващи индекси 11 Dec 2023 10:57 PM (last year)

Разработчици знаят, че тежките заявки могат да подобрят значително бързодействието си при наличие на индекси при колоните, които участват в условието WHERE. Това обикновено води до значително подобрение. Има обаче една техника, която може да ускори нещата дори още повече. Нарича се „покриващи индекси“.

Идеята зад покриващите индекси е да се индексира по всички колони, които участват както в WHERE, така и в SELECT частта на заявката. Нека например имаме таблица users със следните колони: id, username, password и registered_at. Да речем, че ни е нужен списък с потребителските имена на хората, които са се регистрирали през 2022 г. Можем да направим следната заявка:

SELECT username
FROM users
WHERE registered_at >= "2022-01-01 00:00:00" 
         AND 
      registered_at <= "2022-12-31 23:59:59";

Ако индексът е само върху registered_at (*), той ще бъде използван, а след това ще се направят дискови операции за достъп до таблицата, с които ще се прочетат съответните потребителски имена. Тези дискови операции биха могли да бъдат спестени ако индексът се направи по (registered_at, username). Имайте предвид, че последователността е важна - трябва да се направи първо по условието в WHERE, а след това да се изредят колоните в SELECT. Тогава практически всички данни ще бъдат прочетени директно от индекса. Разбира се е важно колоните от текстови тип, които се извличат, да бъдат с достатъчно къси, за да могат да бъдат индексирани в цялост. Тази техника не може да работи за големи обеми от текст.

(*) В MySQL и MariaDB винаги вторичните индекси са съставни, като в тях накрая се добавя първичния ключ по подразбиране. Тоест ако направите индекс по registered_at, този индекс всъщност ще бъде по (registered_at, id). Аналогично индексът по (registered_at, username) ще бъде всъщност индекс по (registered_at, username, id).

 

 

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Дължина на отсечка с краища произволни точки от страни на квадрат 14 Nov 2023 3:19 AM (last year)

Нека е даден квадрат, чиято страна е с дължина [mathi]l[/mathi]. Върху страните на квадрата са избрани произволни точки [mathi]P[/mathi] и [mathi]Q[/mathi]. Каква е вероятността [mathi]|PQ|>l?[/mathi]?

Решение: Нека означим върховете на квадрата [mathi]ABCD[/mathi] така, че т.[mathi]P[/mathi] да лежи на [mathi]AB[/mathi]. Пример за един от възможните случаи е показан на следната картинка:

Имаме четири възможни случая за т.[mathi]Q[/mathi], които са с равна вероятност.

1 случай) Ако т.[mathi]Q[/mathi] лежи на [mathi]AB[/mathi], тогава [mathi]P(|PQ|>l) = 0[/mathi]

2 случай) Ако т.[mathi]Q[/mathi] лежи на [mathi]CD[/mathi], тогава [mathi]P(|PQ|>l) = 1[/mathi]

3 случай) Ако т.[mathi]Q[/mathi] лежи на [mathi]AD[/mathi], ще разгледаме центъра на отсечката [mathi]PQ[/mathi]. Построяваме кръг с център т.[mathi]A[/mathi] и радиус [mathi]\frac{l}{2}[/mathi]. Експериментално може да се провери, че ако [mathi]PQ > l[/mathi], то центъра на [mathi]PQ[/mathi], който ще означим с т.[mathi]M[/mathi] ще лежи вътре в сектора, който се образува при пресичането на кръга с квадрата:

 

Това е така, защото ако означим [mathi]|AP| = x[/mathi] и [mathi]|AQ| = y[/mathi], то

[math]|AM|=|PM|=\frac{|PQ|}{2}=\sqrt{\frac{x^2}{4}+\frac{y^2}{4}}[/math]

Когато т.[mathi]M[/mathi] е вътре в сектора, [mathi]\sqrt{\frac{x^2}{4}+\frac{y^2}{4}} < \frac{l}{2}[/mathi], откъдето [mathi]\frac{|PQ|}{2}<\frac{l}{2}[/mathi] или [mathi]PQ<l[/mathi].

Следователно отсечката ще бъде по-дълга от [mathi]l[/mathi] тогава, когато т.[mathi]M[/mathi] е извън него. Това е лицето на защрихованата част от следната картинка.

Вероятността т.[mathi]M[/mathi] да е вътре в тази зона е:

[math]P(M\notin сектора)=1-P(M\in сектора) = 1-\frac{S(сектора)}{S(малкия квадрат)}=1-\frac{\frac{1}{4}\pi (\frac{l}{2})^2}{(\frac{l}{2})^2}=1-\frac{\pi}{4}[/math]

4 случай) Ако т.[mathi]Q[/mathi] лежи на [mathi]BC[/mathi], вероятността ще е същата както в случай 3, защото решенията са симетрични.

От тук решението на задачата е обединението на тези четири случая, т.е.:

[math]P(|PQ|>l) = \frac{0+1+1-\frac{\pi}{4}+1-\frac{\pi}{4}}{4}=\frac{6-\pi}{8}[/math]

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Триъгълник в квадрат 24 Oct 2023 10:13 PM (2 years ago)

Нека е даден квадрат [mathi]ABCD[/mathi] чиято страна е с дължина [mathi]a[/mathi]. Избираме произволна точка [mathi]P[/mathi] вътре в квадрата. Каква е вероятността [mathi]\triangle ABP[/mathi] да е тъпоъгълен?

Решение: Нека средата на [mathi]AB[/mathi] e точка [mathi]M[/mathi]. Построяваме окръжност с център [mathi]M[/mathi] и радиус [mathi]AM = \frac{a}{2}[/mathi]. Знаем, че ако т. [mathi]P[/mathi] лежи върху тази окръжност, [mathi]\angle APB=90^{\circ}[/mathi]. Ако точката е вътре в полуокръжността (оцветената в жълто част от чертежа), тогава триъгълника ще е тъпоъгълен.

Оттук лесно можем да намерим търсената вероятност. Тя е:

[math]P(\angle APB>90^{\circ}) = \frac{S(полуокръжността)}{S(квадрата)}=\frac{\frac{\pi \times (\frac{a}{2})^2}{2}}{a^{2}}=\frac{\pi \times a^{2}}{8a^{2}}=\frac{\pi}{8}[/math]

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Страниране 17 Oct 2023 1:27 AM (2 years ago)

Когато информацията на някоя страница е много, понякога решаваме да направим т.нар. страниране. Това означава да покажем първите няколко записа и след тях да поставим връзки към следваща страница, на която ще се покажат следващите няколко записа. Тоест даваме възможност на потребителят да прелиства напред-назад като в книга, вместо да му изсипваме цялото съдържание накуп. Как се постига това в MySQL/MariaDB?

Първо решение: LIMIT и OFFSET (бавно; за свободно навигиране; с възможни пропуски при манипулиране на данните по време на извличане на информацията)

Основният начин, по който може да се постигне това, е чрез комбинация от LIMIT и OFFSET върху еднозначно сортирана с ORDER BY поредица от записи. Чрез LIMIT <брой продукти на страница> OFFSET <номер на страница умножен по броя продукти на страница, започвайки от 0> бихме могли да извършим въпросната навигация. Нека дадем пример със следната таблица:

CREATE TABLE products(
   num INT PRIMARY KEY,
   name VARCHAR(255) NOT NULL,
   price DECIMAL(5,2) NOT NULL
);
INSERT INTO products(num, name, price) VALUES 
(59, "A", 25.50), (12, "B", 43.70), (110, "C", 41.30),
(15, "D", 110.12), (85, "E", 200.00), (5, "F", 21.40),
(1, "G", 134.99), (66, "H", 15.84), (300, "I", 71.00);

Да речем, че искаме да показваме по два записа на страница, като всичко ще е подредено по азбучен ред. Заявката за първа страница би била следна:

SELECT name, price FROM products
ORDER BY name, num
LIMIT 2 OFFSET 0;

За втора страница би била:

SELECT name, price FROM products
ORDER BY name, num
LIMIT 2 OFFSET 2;

За трета страница OFFSET ще е 4, и т.н. (номер на страницата, започвайки от 0, умножен по броя на записите в LIMIT). Забележете, че освен по име, сортираме за всеки случай и по първичния ключ. Това се прави, за да направи сортирането детерминистично (еднозначно) и винаги да се гарантира една и съща подредба. Ако не сортираме по num, при повтарящо се име на продукт бихме могли да получим потенциално различна подредба от една и съща заявка.

Този подход е много удобен, защото спокойно бихме могли да навигираме директно на която си поискаме страница. При него обаче има един недостатък: изтриването на информация променя страниците. Представете си, че потребител е на уеб сайта Ви и разглежда първата страница с продукти. Той би виждал продукти A и B, а на втора страница биха го очаквали продукти C и D. Ако в този момент изтрием продукт A и след това потребителят отиде на втора страница, той ще види продукти D и E, вместо C и D. Това е така, защото продукт C вече е дефакто преместен на първа страница.

Второ решение: Чрез пазене на състоянието (бързо; за последователно навигиране; без пропуски при манипулиране на информацията по време на навигиране)

Алтернативно решение на този проблем е да въведем концепция за съхранение на позицията, на която потребителят се намира текущо, която да е независима от състоянието на базата от данни. Ето как може да стане това:

Ето пример за реализация на тази концепция с примерната таблица. Първата страница се извиква по стандартния начин:

SELECT name, price, num FROM products
ORDER BY name, num
LIMIT 2;
+------+-------+-----+
| name | price | num |
+------+-------+-----+
| A    | 25.50 |  59 |
| B    | 43.70 |  11 |
+------+-------+-----+

След като вече знаем, че последния продукт е бил с име "B" и num=11, то следващият в списъка би могъл да е или с име "B" и по-голям номер, или с име, което е лексикографски след "B". Така втора страница следва да бъде заредена със следната заявка:

SELECT name, price, num FROM products
WHERE (name = "B" AND num>11)
         OR
      (name > "B")
ORDER BY name, num
LIMIT 2;

При това решение винаги продуктите от втора страница ще останат такива, каквито са били, включително ако всички предишни продукти от първа страница бъдат изтрити. Разбира се детерминистичното сортиране тук отново е от ключово значение. Показаният подход обаче има недостатък - при него не можем да се прехвърлим на произволна страница. Различните страници трябва да се зареждат една сред друга, защото всяка следваща зависи от данните, записани в последния елемент на предишната. Това би било подходящо ако например правите уеб страница, която зарежда постепенно нова и нова информация при „скролване“ надолу, но е неизползваемо при свободна навигация.

Трето решение: Оптимизиран LIMIT и OFFSET (бърз, за свободно навигиране; с възможни пропуски при манипулиране на данните по време на извличане на информацията)

Първото решение с OFFSET има и още един недостатък - то е, че при много големи таблици, работи бавно и заема много памет. Второто решение няма проблем с бързината, но вече споменахме неговият основен проблем - не може да се отиде на произволна страница. Дали не може първият вариант да се подобри?

Една често препоръчвана техника, която се справя с този проблем е извършване на отложено свързване (deferred join). Идеята е да се създаде допълнителен индекс по колоните, по които ще се сортира:

ALTER TABLE products ADD INDEX(name, num);

след което заявката с LIMIT и OFFSET да се изпълни по следния начин, използвайки SELF JOIN (примерът е за втора страница):

SELECT p1.name, p1.price FROM products AS p1
JOIN (SELECT num FROM products ORDER BY name, num LIMIT 2 OFFSET 2) AS p2
ON p1.num = p2.num;

Идеята тук идва от следното: вложената в JOIN клаузата заявка (таблица p2) работи само и единствено със създадения индекс - така тя реално НЕ прави дискова операция. Ето пример между оригиналната заявка, в която в SELECT се извличаха name и price:

EXPLAIN SELECT name, price FROM products ORDER BY name, num LIMIT 2 OFFSET 2;
+------+-------------+----------+------+---------------+------+---------+------+------+----------------+
| id   | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+------+-------------+----------+------+---------------+------+---------+------+------+----------------+
|    1 | SIMPLE      | products | ALL  | NULL          | NULL | NULL    | NULL | 9    | Using filesort |
+------+-------------+----------+------+---------------+------+---------+------+------+----------------+

а ето и новата вложена заявка p2, при които price не се извлича, т.е. всичко, което заявката трябва да върне като резултат (num), се съдържа в създадения от нас индекс:

MariaDB [pagination]> EXPLAIN SELECT num FROM products ORDER BY name, num LIMIT 2 OFFSET 2;
+------+-------------+----------+-------+---------------+------+---------+------+------+-------------+
| id   | select_type | table    | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+------+-------------+----------+-------+---------------+------+---------+------+------+-------------+
|    1 | SIMPLE      | products | index | NULL          | name | 1026    | NULL | 4    | Using index |
+------+-------------+----------+-------+---------------+------+---------+------+------+-------------+

От удебеления текст ще видите, че първата заявка използва достъп до диска, докато втората работи само с индекса, което разбира се е много по-бързо. Тоест при предложеното решение самото страниране (заявката p2, с която се премахва излишната информация) ще се случва по-бързо, а после добавянето на нужната за потребителя информация (name, price) се извлича от диска само за намерените редове (което е забавяне, но по правило е по-малко, отколкото техниката с LIMIT и OFFSET с filesort).

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Нестандартна задача с претегляния на монети 28 Sep 2023 3:05 AM (2 years ago)

Имате 10 купчинки с по 10 монети от 2 лева. В една от купчинките монетите са фалшиви. Знаете, че истинска монета от 2 лв. тежи 9 грама, а фалшива монета тежи 8 грама. Имате и много прецизен електронен кантар. Как може само с ЕДНО претегляне да определите коя е купчинката с фалшиви монети?

Решение: Номерирайте купчинките от 1 до 10. Извадете 1 монета от втора купчинка, 2 монети от трета купчинка, 3 монети от четвърта купчинка, ... , 9 монети от десета купчинка. Останалите монети са общо 10+9+8+7+...+1, т.е. 55 на брой. Ако всички бяха истински, те биха тежали 495 грама. Когато измерите всички обаче ще установите, че заради наличието на една или повече фалшиви монети, тежестта ще е по-ниска с X грама. Номерът на купчинката с фалшиви монети ще е 11-X.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Играта с плувеца и гоблина 6 Jul 2023 6:00 AM (2 years ago)

Дадено е кръгло езеро. Един плувец влиза да се къпе в него. Изведнъж на брега се появява гоблин. За щастие лошият гоблин не може да плува. За нещастие той е много по-бърз от плувеца.

Изтеглете проекта със сорс кода от тук: GoblinsLake

Проучете по какъв алгоритъм гоблина обикаля езерото. Намерете слабото му място и измислете тактика, с която да излезете в зеленото поле без той да ви хване. Проучете каква е пределната скорост на гоблина, над която ще е невъзможно да се избяга. Помислете дали може да се подобри алгоритъма на гоблина.

П.П. Тази игра не е подходяща за училище, защото движението по окръжност не е просто и лесно за реализиране действие. Може да се представи само при напреднали ученици в кръжочна форма. Хубава е за упражнение от страна на студенти.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Монитори и семафори в Java 4 Jul 2023 2:06 AM (2 years ago)

Вече съм показвал няколко примери с употребата на монитори. Зад кадър в тях стои т.нар. мютекс (mutex) - представете си го като ключалка (променлива със стойности „отключено“ и „заключено“). Идеята е, че когато някоя нишка заключи мютекса, други могат да видят това и съответно да спрат и да изчакат, докато тя си свърши работата. Мониторите автоматизират този процес, като организират централизирано управлявана опашка за изчакване на ресурсите. Това се прави чрез синхронизирани блокове или синхронизирани методи. Тук просто ще припомня с елементарен пример.

Нека имаме прост брояч и две нишки, които конкурентно една на друга го увеличават. Първоначално ще е без синхронизация, т.е. очаквано ще има т.нар. race condition:

private static Integer count = 0;

public static void main(String[] args) throws InterruptedException {
   Thread incr1 = new Thread(){
      public void run(){
         for(int i=0; i<100000; i++){
            count++;
         }
      }
   };
   Thread incr2 = new Thread(){
      public void run(){
         for(int i=0; i<100000; i++){
            count++;
         }
      }
   };
   incr1.start();
   incr2.start();
   incr1.join();
   incr2.join();
   System.out.println(count);
}

Очаквано накрая броячът няма да даде 200000, а по-малко число - някои операции за увеличение са се припокрили една друга, защото те не са атомарни. Заключването с монитор ще разреши този проблем и увеличаването на брояча ще бъде синхронизирано:

private static Object monitor = new Object();
private static Integer count = 0;

public static void main(String[] args) throws InterruptedException {
   Thread incr1 = new Thread(){
      public void run(){
         synchronized(monitor){
            for(int i=0; i<100000; i++){
               count++;
            }
         }
      }
   };
   Thread incr2 = new Thread(){
      public void run(){
         synchronized(monitor){
            for(int i=0; i<100000; i++){
               count++;
            }
         }
      }
   };
   incr1.start();
   incr2.start();
   incr1.join();
   incr2.join();
   System.out.println(count);
}

Реално първата нишка, която изпълни своя synchronized блок ще „заключи“ мютекса зад монитора и по този начин другата няма да може да продължи, докато той не бъде отключен - тя ще се нареди на опашка, за да чака реда си. В Java всеки обект има вграден монитор.

Семафорите от своя страна позволяват паралелна работа на повече от една нишка, но им слага горен лимит. Ако например лимитът е 5, това означава, че до пет нишки могат да работят паралелно, а ако дойде шеста - тя вече ще трябва да чака по подобие на случващото се при монитора. Може да приемете опростено мониторите като семафори с лимит 1.

Ще демонстрирам как се работи със семафори в Java чрез задача, в която нишките ще се борят за ограничен споделен ресурс, като този път ще използвам вграден клас java.util.concurrent.Semaphore (в предишни примери съм показвал подобна задача, но изцяло с ръчна синхронизация и употреба на wait() и notify(), което е изключително трудоемко и объркващо). Представете си, че няколко хора влизат в кафене. За съжаление има само два свободни стола за сядане. Идеята е първите двама, които стигнат до столовете, да седнат на тях, а останалите да ги изчакат на опашка. Когато някой стане, най-дълго чакалия ще седне на неговото място веднага. Ето примерна реализация на това:

public class Philosophers {
   public static void main(String[] args) throws InterruptedException {
      Thread t1 = new Thread(new Client("Karl", "Marx"));
      Thread t2 = new Thread(new Client("Friedrich", "Nietzsche"));
      Thread t3 = new Thread(new Client("Immanuel", "Kant"));
      Thread t4 = new Thread(new Client("Muhammad", "Abduh"));
      Thread t5 = new Thread(new Client("Bertrand", "Russell"));
      t1.start();
      t2.start();
      t3.start();
      t4.start();
      t5.start();
   }
}

record Client(String firstname, String lastname) implements Runnable {
   private static Semaphore sem = new Semaphore(2);
   public void run() {
      try {
         System.out.println(firstname + " " + lastname + " отива към масата...");
         sem.acquire();
         System.out.println(firstname + " " + lastname + " седна на масата и започна да яде...");
         Thread.sleep(3000);
         System.out.println(firstname + " " + lastname + " се наяде и освобождава масата!");
         sem.release();
      } catch (InterruptedException ex) {
         System.err.println("Нещо се обърка при " + firstname + " " + lastname);
      }
   }
}

В получер шрифт е отбелязано как се дефинира семафора, как се заключва и как се отключва. Именно метод acquire() е блокиращ - ако в семафора няма свободни слотове за нишки, тази, в която е изпълнен, ще трябва да чака да се освободи.

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?

Бързо степенуване 3 Jul 2023 2:04 AM (2 years ago)

Степенуването е основна математическа операция и е очаквано да се използва често. Интуитивната реализация на алгоритъм за изчисление на [mathi]x^{n}[/mathi] би била „умножаваме [mathi]x[/mathi] по себе си [mathi]n[/mathi] на брой пъти“. Тоест нещо подобно на следното:

static BigInteger naivePow(BigInteger x, long n){
   BigInteger result = BigInteger.ONE;
   for (long i = 0; i < n; i++) {
      result = result.multiply(x);
   }
   return result;
}

С това решение при достигане до прекалено големи числа ще започне да се отнема сериозно време. Например на компютъра, на който пиша в момента тази статия (Intel Core-i5 9400) изчислението на [mathi]569890561^{121391}[/mathi] отнема около 8 секунди. Не може ли да се случи по-добре?

Основният проблем с бързината идва от там, че извършваме [mathi]n[/mathi] на брой умножения. Вместо това бихме могли да се възползваме от следното наблюдение:

Ето един бърз пример как това може да получи приложение. Представете си, че трябва да изчислим [mathi]5^8[/mathi]. С представената интуитивна реализация ще пресметнем [mathi]5.5.5.5.5.5.5.5=5^{8}[/mathi], т.е. 8 умножения. Вместо това можем да подходим със следната последователност:

  1. Изчисляваме [mathi]5.5=5^{2}[/mathi];
  2. Изчисляваме [mathi]5^{2}.5^{2}=5^{4}[/mathi] (като [mathi]5^{2}[/mathi] е вече пресметнато в предишната стъпка число);
  3. Изчисляваме [mathi]5^{4}.5^{4}=5^{8}[/mathi]

Оказва се, че го направихме с едва 3 умножения. Остава да алгоритмизираме този процес. Най-популярната реализация се нарича „степенуване чрез повдигане на квадрат и умножение“ (square and multiply). При него се възползваме от спецификите на двоичната бройна система и най-вече, че операцията „повдигане на квадрат“ е изключително лека - просто се добавя 0 в края на числото. Ще го демонстрирам директно с пример. Нека да речем, че трябва да изчислим [mathi]5^{45}[/mathi]. Представяме числото 45 в бинарен вид:

[math]101101_{2}[/math]

Нека номерираме битовете с индекси отляво надясно с 1, 2, 3, 4, 5 и 6. Тогава за всеки от тях ще имаме следното:

  1. [mathi]5^{1_{2}}=5^{1}[/mathi];
  2. [mathi]5^{1_{2}}.5^{1_{2}}=5^{10_{2}}=5^{2}[/mathi];
  3. [mathi]5^{10_{2}}.5^{10_{2}}.5^{1_{2}}=5^{101_{2}}=5^{5}[/mathi];
  4. [mathi]5^{101_{2}}.5^{101_{2}}.5^{1_{2}}=5^{1011_{2}}=5^{11}[/mathi];
  5. [mathi]5^{1011_{2}}.5^{1011_{2}}=5^{10110_{2}}=5^{22}[/mathi];
  6. [mathi]5^{10110_{2}}.5^{10110_{2}}.5^{1_{2}}=5^{101101_{2}}=5^{45}[/mathi];

Вижда се как на всяка стъпка след първата се извършва повдигане на квадрат (когато конкретния бит е 0) или повдигане на квадрат и умножение по числото на 1-ва степен (когато конкретния бит е 1). Ето и как се реализира алгоритъма рекурсивно:

static BigInteger fastPowRecursive(BigInteger x, long n){
   if(n==0){
      return BigInteger.ONE;
   }
   BigInteger half = fastPowRecursive(x, n/2);
   BigInteger squared = half.multiply(half);
   if((n % 2)==0){
      return squared;
   } else {
      return squared.multiply(x);
   }
}

Ще забележите веднага, че тази реализация ще даде резултат изключително по-бързо, отколкото предишното решение. Итеративната реализация освен това ще използва и по-оптимално паметта:

static BigInteger fastPowIterative(BigInteger x, long n){
   BigInteger result = BigInteger.ONE;
   while(n > 0){
      if((n % 2) == 1){
         result = result.multiply(x);
      }
      x = x.multiply(x);
      n = n / 2;
   }
   return result;
}

Бихте могли допълнително да подобрите бързодействието ако използвате директно побитови операции.

П.П. Този алгоритъм освен това получава изключително често приложение в криптографията, където често се налагат изчисления от типа [mathi]x^{n} mod(m)[/mathi] (например при алгоритъма RSA). Стандартно може да се помисли първо да се изчисли степенуването [mathi]x^{n}=A[/mathi], а след да се намери остатъка от деление [mathi]A mod(m)[/mathi]. По-оптимален вариант би бил да се извършва делението по модул на всяка стъпка от алгоритъма - това няма да промени крайния резултат (проверете). Вярно е, че така броят на извършените операции се увеличава, но за сметка на това вече не се налага да се работи с много големи числа, т.е. заетата памет значително намалява.

П.П.2. Единственият недостатък на така показания алгоритъм е, че при единичен бит се извършва една операция повече (square + multiply), отколкото при нулев (само square). Това прави алгоритъмът податлив на т.нар. "side channel attacks". Едно възможно решение е алгоритъмът на Монтгомери. Негова примерна реализация е следната:

static BigInteger montgomeryPow(BigInteger x, long n) {
   BigInteger x1 = x;
   BigInteger x2 = x.multiply(x);
   // взима броя битове на числото (премахвайки нулевите в началото)
   int n_bits_len = Long.SIZE - Long.numberOfLeadingZeros(n);
   // обхождаме числото бит по бит, пропускайки най-старшия
   for(int i = n_bits_len-2; i >= 0; i--){
      // (n & (1 << i)) >> i връща i-ти бит на числото n
      if (((n & (1 << i)) >> i) == 0) {
         x2 = x1.multiply(x2);
         x1 = x1.multiply(x1);
      } else {
         x1 = x1.multiply(x2);
         x2 = x2.multiply(x2);
      }
   }
   return x1;
}

Add post to Blinklist Add post to Blogmarks Add post to del.icio.us Digg this! Add post to My Web 2.0 Add post to Newsvine Add post to Reddit Add post to Simpy Who's linking to this post?