Put the misc. stuff in the top dir.
@@ -1,50 +0,0 @@
|
||||
#+title: Atem: a new word
|
||||
#&summary
|
||||
A presentation of the new word 'atem' and why it's so desperately needed
|
||||
#&
|
||||
#+license: wtfpl
|
||||
#+startup: showall
|
||||
|
||||
* Atem: a new word
|
||||
|
||||
Have you ever checked the Wiktionary entry for 'meta'? I have. It's right
|
||||
[[http://en.wiktionary.org/wiki/meta#English][here]]. When I looked at it, I noticed that there were no antonyms. *None!*
|
||||
|
||||
But why?
|
||||
|
||||
#+caption: This alien agrees.
|
||||
#&img;url=/img/aliens/lulala.png,float=right,width=200
|
||||
I often find it useful to be able to un-metaize complex thoughts: instead of
|
||||
thinking about thinking (meta-thinking), I think. Nothing else. However, when I
|
||||
mention that "I think", it may not be obvious that before I was thinking, I was
|
||||
thinking about thinking, which is why I have chosen to create *atem*, a new
|
||||
word whose only function is to act as meta's antonym. With this word, I can now
|
||||
say that "I atem-think", meaning "I think because I thought of thinking", or I
|
||||
can say that "I think", meaning "I think". 'atem' removes a lot of ambiguity
|
||||
from the English language.
|
||||
|
||||
Ok, maybe not that often, but sometimes it's useful.
|
||||
|
||||
Also, *atem* could be quite useful in abstract definitions, as a way to focus
|
||||
on making something abstract concrete instead of making something concrete
|
||||
abstract. For example, this page is probably an atem-page, because somewhere
|
||||
out there there's a page about this page.
|
||||
|
||||
Perhaps every object in existence could be considered an atem object. It's not
|
||||
impossible, it just doesn't make much sense.
|
||||
|
||||
Still, this word could be useful. I hope it gets into a dictionary.
|
||||
|
||||
|
||||
* Update, February 11, 2012 (UTC)
|
||||
|
||||
I just found out that I'm not the only one who at some point found the lack of
|
||||
a meta antonym strange and annoying. Naturally, I can't rely on Wiktionary to
|
||||
give me the latest opinions on language extensions.
|
||||
|
||||
A recent internet search for "meta antonym" gave me several links to pages
|
||||
where other people discussed the need. Someone have even proposed the word
|
||||
"mesa". I don't care if the new antonym becomes "atem", "mesa" (which I guess
|
||||
has nothing to do with [[https://en.wikipedia.org/wiki/Mesa_(computer_graphics)][this Mesa]]), or something else --- I just want it to
|
||||
exist.
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#+title: CSS failings
|
||||
#&summary
|
||||
A travel through my past Cascading Style Sheets mistakes
|
||||
#&
|
||||
#+license: wtfpl
|
||||
|
||||
* CSS failings
|
||||
|
||||
Once, I did not know about Cascading Style Sheets, or CSS. I knew HTML... What
|
||||
else would there be to know?
|
||||
|
||||
Oh, and I knew the =font= tag. It's safe to say my websites were not optimal.
|
||||
|
||||
|
||||
** px in font-size
|
||||
|
||||
First, my apologies for not using the em&emph unit in font-size attributes. For
|
||||
years I have consistently used the px&emph unit when setting the sizes of
|
||||
fonts. I recently found out how wrong this is, how an incredibly arrogant
|
||||
offense to the universe it is, and I have begun correcting this mistake.
|
||||
|
||||
Why is it wrong, you ask? I once thought about that, because I had read
|
||||
somewhere that it was best to use em&emph. But I didn't fully understand the
|
||||
unit, and I certainly didn't want my precious design to be viewed differently
|
||||
by different users! I wanted to force every user to view the exact same render
|
||||
of my pages. This was not ill-meant; I think it originated because of general
|
||||
browser incompabilities and was then taken to an unfortunate extreme.
|
||||
|
||||
Essentially, it's wrong because it {forces the user to view the text in a
|
||||
specific size}&emph.
|
||||
|
||||
If I had read that earlier on, I wouldn't have made so many px-based CSS's.
|
||||
@@ -1,211 +0,0 @@
|
||||
#+title: Digital sikring mod gennemførsel af eksamen en realitet
|
||||
#&summary
|
||||
A text about the failings of digital education and "copy protection". In
|
||||
Danish.
|
||||
#&
|
||||
#+license: wtfpl
|
||||
#+language: da
|
||||
|
||||
Jeg sendte denne besked til Undervisningsministeriet som så fortalte mig at de
|
||||
skam nok var i gang med at gøre det nemmere for "Linus"..
|
||||
|
||||
Sendt 8. marts 2011. Se også <@eval macros.titlelink('stadig-digital-sikring')@>.
|
||||
|
||||
* Digital sikring mod gennemførsel af eksamen en realitet
|
||||
|
||||
At gennemføre en skriftlig eksamen som elev på en gymnasial uddannelse er ikke
|
||||
nemt efter Undervisningsministeriet har indført låse uden nøgler på udleverede
|
||||
cd'er. Problemet bag er dog meget dybere: Digitaliseringen er fejlet.
|
||||
|
||||
Jeg går på htx (teknisk gymnasium) på 3. og sidste år[fn:nomore]. For ikke lang
|
||||
tid siden var jeg til skriftlig terminsprøve i engelsk A hvor terminsprøven var
|
||||
en kopi af eksamen fra juni 2010. Som elev er man ofte lidt nervøs før man skal
|
||||
op til en eksamen. Har man forberedt sig godt nok? Har man glemt noget? Derfor
|
||||
er det vigtigt for eleverne at eksamenen — eller her terminsprøven — er med så
|
||||
få problemer som muligt, helst ingen overhovedet. Spild af tid kan være
|
||||
frustrerende for alle parter.
|
||||
|
||||
En eksamen eller terminsprøve i skriftligt engelsk består af to dele: en
|
||||
grammatikdel, hvor man i en time sidder og løser opgaver i hånden, og en
|
||||
stildel, hvor man har fire timer foran sin egen bærbare computer til at læse et
|
||||
oplæg, læse baggrundsmateriale, se et par korte videoklip der følger med og så
|
||||
skrive stilen. Alt materialet til stilen får man udleveret på en cd. At skrive
|
||||
i hånden i en time kan vi — trods alt — godt formå, men man skulle tro at den
|
||||
anden del, hvor vi bruger vores egen computer, skulle være nemmere for os da
|
||||
mange af os er vant til at skrive på computer. Imidlertid har
|
||||
Undervisningsministeriet valgt at indføre meningsløse begrænsninger der gjorde
|
||||
at jeg skulle vente 35 minutter på at få oplægget og
|
||||
baggrundsmaterialet. Grunden hertil var at cd'erne var kopisikrede på en sådan
|
||||
måde at et af styresystemerne Microsoft Windows eller Apple Mac OS X var
|
||||
krævet. Jeg bruger imidlertid et andet styresystem, kaldt GNU/Linux. Dette er
|
||||
et frit system hvor det er brugeren der styrer computeren, og ikke computeren
|
||||
der styrer brugeren, som det er tilfældet i fx Microsofts produkter og Apples
|
||||
produkter — mere om det senere. Hovedsagen her var at jeg var nødt til at vente
|
||||
til en af skolens it-hjælpere brød kopisikringen på en Windows-computer og gav
|
||||
mig filerne i deres rå form på en usb-nøgle, så min computer kunne læse
|
||||
dem. Problemet med cd'en var at vigtige dokumenter, såsom oplægget, var gemt i
|
||||
et filsystem jeg ikke havde adgang til grundet mit bevidste valg om ikke at
|
||||
bruge hverken Windows eller Mac.
|
||||
|
||||
Da vi fik udleveret cd'erne, stod der rigtigt nok på dem at de kun virkede på
|
||||
Windows og Mac. Jeg har siden været inde på Undervisningsministeriets
|
||||
hjemmeside (se uvm.dk/Uddannelse/Gymnasiale uddannelser/Proever og
|
||||
eksamen/Tekniske specifikationer.aspx), og det viser sig at dette fortsætter i
|
||||
samme linje, bare værre. Kravene til skriftlig eksamen i fysik A i foråret 2011
|
||||
er mere eller mindre de samme som til engelsk A, men i fysik skal man også have
|
||||
software installeret der understøtter Word 2003- og Excel 2003-filer. Begge
|
||||
disse type computerfiler fra Microsoft er i formater hvis specifikationer ikke
|
||||
er tilgængelige, og det er derfor endnu ikke lykkedes at få fuld support for
|
||||
formaterne i programmer der ikke har været inde over Microsoft. Man vil altså
|
||||
være tvunget til at bruge en variant af programmerne fra Microsoft Office for
|
||||
at læse filerne fuldstændigt hvilket hverken er muligt eller ønsket når man er
|
||||
bruger af et frit system. Desuden — og dette er ret så relevant — følger
|
||||
Undervisningsministeriet her ikke nogen af de to obligatoriske standarder for
|
||||
dokumentudveksling som alle offentlige myndigheder har skullet bruge
|
||||
siden 2008. Pjecen "Sådan anvender du åbne standarder for software i det
|
||||
offentlige" fra IT- og Telestyrelsen forklarer ellers disse standarder ret
|
||||
tydeligt. Måske har Undervisningsministeriet indkøbt deres it-løsning
|
||||
før 1. januar 2008, så de ikke er tvunget til at bruge de nye standarder, men
|
||||
at bruge et 8 år gammelt programafhængigt dokumentformat, når et et
|
||||
standardiseret et, som nemt kan læses af alle styresystemer, har været
|
||||
anbefalet i over 3 år, burde ikke være acceptabelt. Undervisningsministeriet
|
||||
har ikke fået nok undervisning.
|
||||
|
||||
Jeg har ikke fysik A, men en fra min klasse der kører GNU/Linux ligesom mig
|
||||
har, og hvis han skal op til eksamen til maj, kan han risikere ikke fuldt ud at
|
||||
kunne læse opgaven — ikke kun fordi cd'en er kopibeskyttet, men også fordi
|
||||
filerne kun kan læses helt korrekt af Microsoftrelaterede
|
||||
programmer. Programmer, mange mennesker over hele verden har valgt ikke at
|
||||
bruge af moralske årsager.
|
||||
|
||||
Men hvad er alt dette softwarefrihed for noget? Nogen vil måske tænke at jeg jo
|
||||
bare kunne skifte til Mac eller Windows og derefter installere alle de
|
||||
computerprogrammer folk ville have jeg skulle installere. Dette er dog ikke en
|
||||
holdbar løsning. Faktisk kommer problemet med de kopisikrede cd'er og de uåbne
|
||||
formater fra noget meget dybere, noget meget værre og noget virkeligt udbredt:
|
||||
proprietær software. Proprietær software er software som kun ophavsretholderen
|
||||
bestemmer over, dvs. brugeren er begrænset af licensaftaler. Disse aftaler er
|
||||
forskellige, men fælles er at man sjældent har mange softwarelaterede
|
||||
rettigheder tilbage når man har sagt ok til en sådan aftale. Hvis man bruger
|
||||
proprietær software, har man ikke kontrol over de programmer man kører, over
|
||||
selve brugen af ens computer. Menneskerne der står bag programmet har
|
||||
kontrol. Og de bruger den kontrol.
|
||||
|
||||
Mange kan nok huske skandalen med e-bookreaderen Kindle (i visse kredse nu
|
||||
kaldt "Swindle") hvor flere mennesker fik slettet bogen "1984" som de havde
|
||||
købt. Dette kunne ske fordi styresystemet på Swindlen er proprietært og altså
|
||||
ikke bliver styret af brugerne af det. Efter en retssag sagde Amazon.com, dem
|
||||
bag sletningen, ok til i fremtiden kun at slette bøger under særlige
|
||||
omstændigheder. Hvis dette ikke var uhyggeligt, ville det være grinagtigt: at
|
||||
der skal en retssag til før en virksomhed vælger ikke at slette bøger fra
|
||||
elektroniske dimser via internettet. Men sådan er proprietær software:
|
||||
utilregneligt og ubrugeligt.
|
||||
|
||||
Der er mange andre eksempler på proprietær software: Microsoft Windows sender
|
||||
uforklarede beskeder til Microsoft en gang imellem, Adobe Photoshop kører kun
|
||||
hvis man har indtastet en speciel nøgle, Facebook indsamler data, censurerer
|
||||
noget, giver andet videre til annoncører, og har fuld mulighed for at gøre mere
|
||||
med dataen, hvilket de nok også gør, og i Apples iPhone og iPad (i
|
||||
"Swindle"-kredsene kaldt "iBad") er det Apple — og ikke forbrugeren — der
|
||||
bestemmer hvilke programmer der må gøres tilgængelige og installeres. I alle
|
||||
tilfælde handler det om kontrol. Virksomhederne, grupperne eller
|
||||
enkeltpersonerne bag ønsker så meget magt som muligt, for de vil tjene mange
|
||||
penge.
|
||||
|
||||
Som computerbruger er man nødt til på et tidspunkt at tænke over hvad der er
|
||||
vigtigst: softwareejernes velvære eller samfundets digitale frihed. For et par
|
||||
år siden valgte jeg friheden fremfor fængslet og skiftede altså til
|
||||
GNU/Linux. Mange før mig havde gjort dette, så det var nemt at komme i gang med
|
||||
mit nye system på min computer. Det er nemt nok til at mine 50+-forældre kan
|
||||
finde ud af det. Kernen i frie systemer såsom GNU/Linux er fri software. Fri
|
||||
software er software der gør brugeren fri vha. disse fire friheder:
|
||||
|
||||
1. Friheden til at køre programmet for et hvilket som helst formål
|
||||
2. Friheden til at studere programmet og ændre i det. Kildekoden til
|
||||
programmet skal være tilgængelig for at dette er muligt
|
||||
3. Friheden til at dele programmet med alle
|
||||
4. Friheden til at ændre i programmet og dele ens ændringer
|
||||
|
||||
Fri software er altså det præcist modsatte af proprietært software. Her er
|
||||
brugeren den vigtigste, for det er brugeren der skal køre programmet. Tilsammen
|
||||
sørger de fire friheder, oprindeligt defineret i sammenhæng med begyndelsen af
|
||||
organiseret udvikling af fri software i midten af 1980'erne, for at ens
|
||||
computer ikke misbruger ens data og ikke begrænser adgangen til og brugen af
|
||||
ens data. Fri software handler ikke om styrken af det tekniske kodestads der
|
||||
ligger bag programmet. Det handler om friheden forbundet med det. I mange
|
||||
tilfælde er fri software dog virkeligt funktionelt, og fx kører langt de fleste
|
||||
hjemmesider netop på fri software. Det fungerer.
|
||||
|
||||
Nogen vil måske opfatte nogle eller alle af de fire friheder for
|
||||
irrelevante. Men går man gennem dem trin for trin, giver de god mening. Først
|
||||
og fremmest: det giver ingen mening at have et program hvis skaber(e) har
|
||||
bestemt du ikke må køre. Det er en bunke bytes som ikke kan fås til at bevæge
|
||||
sig. Her vil nogen måske proteste med henblik på økonomi og påstå at det er
|
||||
nødvendigt at begrænse ens brug af et program indtil man har købt en unik
|
||||
nøgle, for at virksomheden bag kan tjene penge og udvikle nyt software. Dette
|
||||
argument leder tråden væk fra hovedproblemet, nemlig at man skal kunne
|
||||
kontrollere hvad der sker på ens egen computer. Det er dog sandt at det er
|
||||
nemmere at tjene store penge ved at tvinge dem ud af folk — hvilket er det
|
||||
kommercielt proprietær software gør — end ved at bede folk om dem. Der er
|
||||
imidlertid intet galt med fri kommerciel software. Det er betydeligt sværere at
|
||||
blive softwaremilliardær når man sælger fri software istedet for proprietær
|
||||
software, men økonomiske modeller der respekterer softwarefrihed eksisterer
|
||||
skam: man kan fx yde support eller lave skræddersyede løsninger. At have
|
||||
kontrol nok over et program til at kunne køre det bør altså være et must, lige
|
||||
meget om man går op i penge eller ej.
|
||||
|
||||
Det giver heller ingen mening at have et program man ikke må dele. Det er
|
||||
gavnende at dele, og dette gælder især for software. Software er noget man
|
||||
bruger, noget der gør ikke-trivielle ting trivielle, så man kan fokusere på
|
||||
andre, mere interessante ting. Og hvis ens ven har brug for at kunne gøre noget
|
||||
på sin computer, og man har et program der kan gøre netop det, så ville det
|
||||
være mærkeligt ikke at dele programmet med vennen. Programmet er immaterielt,
|
||||
og man mister det ikke ved at dele det. Alt er bare kopier. Mange store
|
||||
virksomheder har i lang tid spredt propaganda om at man er en "pirat" hvis man
|
||||
deler software. Pladeselskaberne er med på denne magtjagt, men for dem handler
|
||||
det om kulturelle værker. For folk der deler betyder det dog ikke så meget hvem
|
||||
der står bag propagandaen. Det vigtigste er at protestere mod den og ikke
|
||||
begynde at tro på den. Hvis man ikke må dele et program, må man lade være med
|
||||
at bruge det. Folk der producerer fri software ønsker at folk kopierer fri
|
||||
software til venner, bekendte og fremmede.
|
||||
|
||||
Selv hvis man kan blive enig med de to forrige forklaringer, vil en del sikkert
|
||||
stadig mene, at de to friheder angående ændring af programmer virker stort set
|
||||
overflødige: almindelige mennesker er jo ikke programmører, og de vil derfor
|
||||
ikke kunne ændre noget lige meget hvad. Disse to friheder handler dog ikke
|
||||
nødvendigvis om at man skal ændre et program selv. Hvis man ikke kan, men har
|
||||
brug for, at ændre et program, skal man kunne hyre nogen der har styr på
|
||||
programmering til at gøre det for en. Frihederne har også et andet, lige så
|
||||
vigtigt formål: når alle frit kan studere koden bag et program, er
|
||||
sandsynligheden for at programmet ikke er ondskabsfuldt uendeligt større end
|
||||
hvis koden ikke var tilgængelig. Hvis der er noget ondskabsfuldt i, kan en
|
||||
eller anden programmør fjerne det og lave en ny version af programmet. Hvis
|
||||
programmet ikke virker, kan en eller anden programmør få det til at virke. I
|
||||
mange tilfælde samarbejder frivillige programmører på tværs af landegrænser i
|
||||
decentraliserede grupper over internettet, og hvis ikke alle kunne studere
|
||||
koden, forbedre den og sprede ideer om implementeringer af diverse algoritmer
|
||||
mm., ville mange af de udbredte frie programmer der bruges i dag ---
|
||||
OpenOffice.org, fx — ikke eksistere i deres udviklede tilstand. Der er dog også
|
||||
rigtig meget fri software der udvikles af enkeltpersoner, men også her giver
|
||||
alle fire friheder mening.
|
||||
|
||||
Fri software er godt for samfundet, ligesom ytringsfrihed er godt, og det er
|
||||
derfor bekymrende at fx Undervisningsministeriet har valgt at alliere sig med
|
||||
virksomheder der producerer proprietær software. Der er sket meget siden GNU
|
||||
(GNU's Not Unix, se gnu.org) og FSF (Free Software Foundation, se fsf.org),
|
||||
henholdsvis et fri software-projekt og en fri software-organisation, begyndte
|
||||
spredningen af fri software i '80'erne, men fri software er ikke færdigt med at
|
||||
blive udbredt endnu. I Danmark virker det som om myndighederne ikke har fulgt
|
||||
helt med udviklingen generelt hvilket bl.a. kom til udtryk ved terminsprøven
|
||||
hvor vi fik udleveret noget så arkaisk som cd'er (i dag har cd'er lidt samme
|
||||
status som disketter havde for 5 år siden). En del fra min klasse havde ikke
|
||||
cd-drev i deres laptops, og de sad ligesom mig og ventede i en god halv time
|
||||
før en usb-nøgle reddede os. Der er simple, tidsbesparende, snydsikre
|
||||
alternativer til uddelinger af skiver — man kunne fx sætte et trådløst netværk
|
||||
op hvor kun oplægget kunne hentes — men dem bruger man ikke. Desværre.
|
||||
|
||||
I april er der en digitaliseringskonference i Aarhus. Jeg håber der kommer
|
||||
noget godt ud af den.
|
||||
|
||||
|
||||
[fn:nomore] Det er jeg ikke længere. Jeg blev student i juni.
|
||||
@@ -1,71 +0,0 @@
|
||||
#+title: Digital freedom
|
||||
#&summary
|
||||
A discussion about digital freedom in general.
|
||||
#&
|
||||
#+license: wtfpl
|
||||
#+startup: showall
|
||||
|
||||
#&+classes=warning
|
||||
This is a work in progress (more so than my other articles).
|
||||
#&
|
||||
|
||||
* Concepts
|
||||
|
||||
(Currently mostly about social networking.)
|
||||
|
||||
I like to follow this rule: When I create something substantial which I want to
|
||||
share, I host it myself. But why? Because I don't want to depend on something
|
||||
which I cannot control or strongly influence.
|
||||
|
||||
A decentralized social network must be widespread for people to be able to share
|
||||
private data with a select few, i.e. the select few must be used to using the
|
||||
decentralized network.
|
||||
|
||||
The difficulty of leaving a service is determined by the complexity of the
|
||||
social features of the service.
|
||||
|
||||
I only host my own works somewhere else than on my own host if I feel that I
|
||||
have a social obligation to do so, or if it's a link that points out of the
|
||||
service. I don't mind if what Facebook ends up being is the new digg.
|
||||
|
||||
The more difficult it is to leave a service, the more I feel I have a *social*
|
||||
obligation to host my works on the service. However, the more difficult it is to
|
||||
leave a service, the more I also feel that I have a *moral* obligation to /not/
|
||||
host my works on the service.
|
||||
|
||||
I don't wish to host substantial works, even public ones, on e.g. Facebook. Not
|
||||
because Facebook gets to know them (I have made sure I don't mind them being
|
||||
public), but because I use a service which I don't like, and that may fuel the
|
||||
use in general, especially for my friends. As such, it doesn't matter what I
|
||||
publish on the service, it will no matter what (in varying degrees) accelerate
|
||||
the use of the service, which I do not want to happen.
|
||||
|
||||
In general, it's a balance. I try not to make others depend on Facebook because
|
||||
of me; I do that by not uploading large photo galleries to Facebook. However,
|
||||
photo galleries on Facebook have quite complex features.
|
||||
|
||||
|
||||
* Hardware freedom links (different views)
|
||||
|
||||
+ [[https://www.fsf.org/resources/hw/endorsement/criteria]]
|
||||
+ [[https://www.fsf.org/campaigns/free-bios.html]]
|
||||
+ [[https://www.gnu.org/philosophy/android-and-users-freedom.html]]
|
||||
+ [[http://projects.goldelico.com/p/gta04-main/page/FirmwareInjector/?rev=322]]
|
||||
+ [[http://www.oreillynet.com/linux/blog/2007/08/the_four_freedoms_applied_to_h.html]]
|
||||
+ [[http://www.boingboing.net/2010/09/19/intel-drm-a-crippled.html]]
|
||||
+ [[http://lists.en.qi-hardware.com/pipermail/discussion/2010-January/001635.html]]
|
||||
+ [[http://www.ofb.biz/safari/article/353.html]]
|
||||
+ [[http://arstechnica.com/business/news/2006/12/8428.ars]]
|
||||
+ [[http://distrowatch.com/weekly.php?issue=20100614#feature]]
|
||||
+ [[http://libreplanet.org/wiki/When_should_firmware_be_free]]
|
||||
+ [[http://www.datamation.com/osrc/article.php/3787736/Proprietary-Firmware-and-the-Pursuit-of-a-Free-Kernel.htm]]
|
||||
+ [[https://lwn.net/Articles/352555/]]
|
||||
+ [[https://lwn.net/Articles/460654/]]
|
||||
+ [[http://lists.goldelico.com/pipermail/gta04-owner/2011-October/000375.html]]
|
||||
+ [[http://lists.goldelico.com/pipermail/gta04-owner/2011-September/000325.html]]
|
||||
|
||||
I think hardware design freedom is as important as software freedom because of
|
||||
the same reasons I think free software is important. The fact that modifying
|
||||
hardware is much more difficult than modifying software is irrelevant as the
|
||||
ability to do so it still useful, and as gaining the knowledge behind a design
|
||||
is also still useful.
|
||||
@@ -1,9 +0,0 @@
|
||||
#+title: Hacking
|
||||
#&summary
|
||||
Hackety hack.
|
||||
#&
|
||||
#+startup: showall
|
||||
|
||||
* Hacking
|
||||
|
||||
I use the term "hacking" to mean "playing with".
|
||||
@@ -1,23 +0,0 @@
|
||||
#+title: Writings
|
||||
#+summary: A list of my writings
|
||||
|
||||
* Writings
|
||||
|
||||
#++eval
|
||||
#+BEGIN_SRC python
|
||||
macros.list_pages()
|
||||
#+END_SRC
|
||||
|
||||
** Pseudo-writings
|
||||
|
||||
+ <@eval macros.titlelink('/projects/magicng/')@>
|
||||
|
||||
|
||||
** Old
|
||||
|
||||
+ [[http://projects.metanohi.name/eonaton/?t=0&s=5][Eon Aton]] (both a story and an unfinished game)
|
||||
|
||||
|
||||
** Purposely crappy
|
||||
|
||||
+ [[./potator/][POTATORR!]]
|
||||
@@ -1,70 +0,0 @@
|
||||
#+title: Licensing on metanohi
|
||||
#&summary
|
||||
What's up with all that stuff?
|
||||
#&
|
||||
#+startup: showall
|
||||
#+license: wtfpl
|
||||
|
||||
* Licensing on metanohi
|
||||
|
||||
I usually just use the Do What The Fuck You Want To Public License, Version 2
|
||||
from [[http://wtfpl.net/]]:
|
||||
|
||||
#+BEGIN_SRC
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
#+END_SRC
|
||||
|
||||
I think the license is fun, and there really is no good reason to use anything
|
||||
else for most of my small, one-off projects. For larger projects, I use BSD2 or
|
||||
BSD3 or whatever -- I accept all free software licenses and really do not wish
|
||||
to discuss them that much (although I admit that I have previously been more
|
||||
opionated).
|
||||
|
||||
|
||||
* Some reasons
|
||||
|
||||
I got tired of software and culture licenses. I don't mind them, and I don't
|
||||
have anything against copyleft -- it's a tool, and it can be effective in some
|
||||
cases -- but for my own projects, I just want to publish something that people
|
||||
can use.
|
||||
|
||||
I still ask for attribution, but I do it in a nice way, and not with the
|
||||
implicit threat of a license. If someone doesn't attribute me, it makes no
|
||||
difference to me whether they have to because of a license; I'm not going to do
|
||||
anything about it anyway.
|
||||
|
||||
I guess that some people consider e.g. CC BY-SA a recognizable symbol and that
|
||||
its law stuff is secondary. I can follow that thought, but I just got tired of
|
||||
it.
|
||||
|
||||
Some people might not want to integrate WTFPL code into their project, but fuck
|
||||
them (okay, in practice I'll probably just relicense to BSD2 or BSD3 if
|
||||
necessary).
|
||||
|
||||
All that being said, I will work in any free software and free culture project
|
||||
no matter what license they use. WTFPL is just for my own junk.
|
||||
|
||||
|
||||
* Copyright in general
|
||||
|
||||
I'm not a fan of copyright as it is right now, but I don't know if it should be
|
||||
removed alltogether (if that was even possible...). I think it would be nice if
|
||||
copyright was only for commercial use.
|
||||
|
||||
|
||||
* Previously
|
||||
|
||||
I used to have a lot of text about this, but I've come to just not care. It's
|
||||
all in the git history if you want to dig it up and read it.
|
||||
|
Before Width: | Height: | Size: 62 KiB |
@@ -1,57 +0,0 @@
|
||||
#+title: Et langt digt (A Long Poem)
|
||||
#&summary
|
||||
Et langt digt jeg skrev for noget tid siden fordi jeg ikke kan lide digte.
|
||||
#&
|
||||
#+license: wtfpl
|
||||
#+language: da
|
||||
|
||||
* Et langt digt
|
||||
|
||||
#&img;url=frontpage.png,height=595,center,medlink=longpoem.pdf,alt=Forside
|
||||
|
||||
Klik på billedet for at downloade digtet i PDF.
|
||||
|
||||
Jeg har et lidt anstrengt forhold til digte. De virker så meningsløse, så
|
||||
ligegyldige, så dumme. Denne holdning er muligvis et resultat af alle de
|
||||
analyser og fortolkninger jeg lavede i slutningen af folkeskolen og på
|
||||
HTX. Argh.
|
||||
|
||||
Derfor har jeg skrevet mit eget digt, påbegyndt efteråret 2010 og færdiggjort
|
||||
efteråret 2011. Der er 2096 linjer og nogle rim hist og her.
|
||||
|
||||
Jeg afslører gerne at der ikke er noget dybere formål med digtet, men jeg er
|
||||
blevet lært at forståelsen af digte i høj grad handler om at man selv skal
|
||||
fortolke dem og prøve at forstå dem, godt nok med afsæt i forfatterens
|
||||
udgangspunkt. Altså vil nogle læsere sikkert få en masse ud af at læse digtet
|
||||
selv om jeg ikke planlagde digtet til at give den effekt.
|
||||
|
||||
Det eneste jeg rigtig har gjort noget ud af er coveret (som jeg er ret stolt
|
||||
af).
|
||||
|
||||
** Uddrag
|
||||
|
||||
#&pre
|
||||
Søren 1 -- ham med en gynge
|
||||
Hørte en dag en fremmed synge
|
||||
Det var hverken Sarræhh eller søsteren
|
||||
Så stemmen var fremmed
|
||||
Han kiggede til højre og venstre, til nord og syd
|
||||
Men hans sanser kunne ikke lokalisere den guddommelige lyd
|
||||
Til sidst gik han ud fra sin grund
|
||||
Hvorefter han faldt ned i et sund
|
||||
|
||||
Når man ved siden af et sund bor
|
||||
Er det dumt at man tror der er jord
|
||||
Jorden er der se'fø'li, dog nok lidt sandet
|
||||
Men den er altså langt nede under vandet
|
||||
#&
|
||||
|
||||
|
||||
** Ofte stillede spørgsmål
|
||||
|
||||
[Ingen har faktisk stillet disse spørgsmål, men jeg kommer fremtiden i møde.]
|
||||
|
||||
*** Men digte er gode! Du har ikke ret når du påstår at digte er dårlige!
|
||||
|
||||
Ikke et spørgsmål.
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#+title: My Universe
|
||||
#&summary
|
||||
I have attempted to define a universe.
|
||||
#&
|
||||
#+startup: showall
|
||||
#+license: wtfpl
|
||||
|
||||
* Introducing My Universe
|
||||
|
||||
Everything is much too complex, so I have defined a simpler universe.
|
||||
|
||||
You can download v0.1 [[myuniverse.pdf][here]].
|
||||
|
||||
You can get the sources at
|
||||
|
||||
: $ git clone git://metanohi.name/myuniverse
|
||||
290
site/misc/na.org
@@ -1,290 +0,0 @@
|
||||
#+title: Na
|
||||
#&summary
|
||||
A new spoken and written language not in development.
|
||||
#&
|
||||
#+license: wtfpl
|
||||
#&toc
|
||||
|
||||
* Na
|
||||
|
||||
** Introduction
|
||||
|
||||
Na is a probalistic language. The more details you use when explaining an
|
||||
event, the more probable it is that the recipient understands you. This is not
|
||||
very different from typical languages ("a blue building" is more precise than
|
||||
"a building"), but the new thing in Na is that this guesswork is everywhere.
|
||||
|
||||
** Alphabet
|
||||
|
||||
Optimally, Na should have its own alphabet. To aid in its spreading, a subset
|
||||
of the Latin alphabet has been chosen instead:
|
||||
|
||||
: . A E I O B D F G K L N S T V
|
||||
|
||||
All of these letters are pronounced as "short sounds", i.e. "A" is not
|
||||
pronounced as "AAY", but just "AE". This is the same for all wovels. There are
|
||||
two types of correct syllables: those of the form <consonant><wovel> and those
|
||||
of the form <wovel>: "LO" is legal, "LOO", "LLA", "LOI", "AV", and "AEV" are
|
||||
not. Aside from letters, only the period (".") character and space between
|
||||
characters are used. No commas, no colons, no semicolons, nothing else. Also,
|
||||
there is no difference between uppercase and lowercase letters. Sentences are
|
||||
read left-to-right (numbers are written right-to-left; more about that later).
|
||||
|
||||
With only 4 wovels and 10 consonants pronouncations can be very varied and
|
||||
still correct. According to the rules laid out above there are 40 different
|
||||
single-syllable words, 40^2 = 1,600 two-syllable words, 40^3 = 64,000
|
||||
three-syllable words, 40^4 = 2,560,000 four-syllable words, etc. At ten
|
||||
syllables (an extreme case) there are 10,485,760,000,000,000 different
|
||||
10-syllable words and a total number of 10,754,625,641,025,640
|
||||
any-number-of-syllables-less-or-equal-to-10 words.
|
||||
|
||||
|
||||
*** TODO IPA/SAMPA
|
||||
|
||||
The author of this document is not very familiar with IPA, SAMPA, or any other
|
||||
phonetic alphabet.
|
||||
|
||||
** Goals
|
||||
|
||||
Na wants to be a useful language somewhat usable by people. Na has been
|
||||
designed to be fairly global, but since the creator of Na is fluent only in
|
||||
Germanic languages (Danish and English), and because the Latin alphabet is
|
||||
used, Na is non-global. Nevertheless, it /wants/ to be global.
|
||||
|
||||
** Basics
|
||||
|
||||
Na has no nouns, no verbs, no adjectives, no adverbiums, no pronouns, etc. In
|
||||
Na, the core of everything is a word more or less equivalent to the English
|
||||
word "existence". This word is *BA*. All other words are based on this base
|
||||
word (in object oriented programming language terminology, this is equivalent
|
||||
to subclassing classes).
|
||||
|
||||
The groups at the first levels of heritance are:
|
||||
|
||||
+ Existence :: BA
|
||||
+ Number :: BE
|
||||
+ Real number :: BEBA
|
||||
+ Integer :: BEBE
|
||||
+ Fraction :: BEBI
|
||||
+ Imaginary number :: BEBO
|
||||
+ Complex number :: BEDA
|
||||
+ Symbol :: BI
|
||||
+ Letter :: BIBA
|
||||
+ Shape :: BO
|
||||
+ Relation :: DA
|
||||
+ Identity :: DE
|
||||
+ Absolute combiner :: DO
|
||||
+ Identifier :: FA
|
||||
+ Relative combiner :: FE
|
||||
|
||||
|
||||
TODO: Improve on groups.
|
||||
|
||||
These have been chosen not because of perfection, but because Na was designed
|
||||
for human beings (who are not perfect). Nevertheless, these groups should
|
||||
suffice for the time being.
|
||||
|
||||
*Note:* These groups are few on purpose. Many words fit into several
|
||||
groups. Groups are only good for basic things; more complex meanings do not
|
||||
have to be placed in any group.
|
||||
|
||||
Na uses a combination of numbers, identifiers and further subclassing to
|
||||
achieve (some) usability. In Na, what is written as one sentence in
|
||||
e.g. English, can often become more than one sentence. To make a statement in
|
||||
Na, one splits one's sentence into Na sentences, the first ones consisting of
|
||||
definitions and assignments (named variables), and the final one consisting of
|
||||
everything put together in the right order. Often, the order does not matter,
|
||||
and the purpose of the final sentence is really just to point out what
|
||||
definitions you have chosen to use, and that you are done.
|
||||
|
||||
For example, to write "I see a table." in Na, you first extract the objects (in
|
||||
Na, everything is an object) from the sentence. This gives us:
|
||||
|
||||
+ I, the subject
|
||||
+ see, the verb
|
||||
+ a table, the object
|
||||
|
||||
In Na, this is simplified further into:
|
||||
|
||||
+ I
|
||||
+ to see
|
||||
+ table, 1
|
||||
|
||||
The only two possible sense-making combinations using all the words would be to
|
||||
say "I see a table" or "The table sees me". To stress that the first version is
|
||||
wanted, we first combine "I" and "to see", which we then combine with a
|
||||
definition of "table, 1". Finally, we throw the definitions together, so that
|
||||
people will understand that the sentence is over.
|
||||
|
||||
To specify "I", we use one of the members from the identity (*DE*) group. "to
|
||||
see" is also an abstraction, because the "I" can see in different ways (if it's
|
||||
a camera, it doesn't use a human brain to see, for example). Other,
|
||||
non-generalized terms are also available, but they are not part of the
|
||||
abstraction group.
|
||||
|
||||
To create a variable to hold "table, 1", you combine the number 1 with a
|
||||
generic table defined using the shape (*BO*) group.
|
||||
|
||||
A sentence where you combine words into a new word has this structure:
|
||||
|
||||
: <word 1> <word 2>[ <word 3>[...]] DO <new word>.
|
||||
|
||||
This is an absolute combination. It is also possible to make relative
|
||||
combinations where word mixes are not saved in new words:
|
||||
|
||||
: <word 1> <word 2>[...] FE <word(s)>[ ...].
|
||||
|
||||
In these relative cases, the words before an FE mark are evaluated when FE is
|
||||
reached. If FE is left out from such sentences, everything will be evaluated at
|
||||
once. Programmers might find it helpful to think of FE as a stack resetter.
|
||||
|
||||
When you do not use the *DO* or *FE* combiner, you state something:
|
||||
|
||||
: <word 1>[ <word 2>[...]].
|
||||
|
||||
In real languages, this is the equivalent of actually expressing something ---
|
||||
combines do not express anything, they merely aid in preparing for later
|
||||
expressions.
|
||||
|
||||
** Example 1: I see a table
|
||||
|
||||
One can write "I see a table." in two ways: the absolute way with *DO* or the
|
||||
relative way with *FE*.
|
||||
|
||||
Words for "I", "to see", and "table" have not yet been made, but we assume they
|
||||
are BIGUHA, NULASE, and GAVOTI, respectively. The integer 1 is FA BEBE B.
|
||||
|
||||
*** Absolute way
|
||||
|
||||
+ Step 1 :: Combine "I" and "to see" into a sentence using combinations from
|
||||
different groups. Give it a name, e.g. VAVO.
|
||||
+ Step 2 :: Combine the number 1 from the integer (*BEBE*) group with the table
|
||||
from the shape group. Give it a name, e.g. GALO.
|
||||
+ Step 3 :: a) Write VAVO GALO, or b) combine VAVO and GALO into e.g. VALO
|
||||
(could be any word) and go to step four.
|
||||
+ Step 4 :: Write VALO.
|
||||
|
||||
So:
|
||||
|
||||
: biguha nulase do vavo. gavoti fa bebe b do galo. vavo galo do valo. valo.
|
||||
|
||||
or, shorter:
|
||||
|
||||
: biguha nulase do vavo. gavoti fa bebe b do galo. vavo galo.
|
||||
|
||||
The advantage of the first variation is that VALO can be reused again and again
|
||||
until people have forgotten what its temporary meaning is. For example, if you
|
||||
are telling a story where the main character often sees a table, you could do
|
||||
this:
|
||||
|
||||
: valo. valo. valo. valo. valo.
|
||||
|
||||
It is not necessary to define new combinations all the time. Na comes with a
|
||||
small built-in set of combinations which is required learning for all Na
|
||||
speakers. These built-in definitions should be used whenever possible,
|
||||
eventually in subclassed or changed forms, to make it easier to write --- and
|
||||
especially speak --- Na.
|
||||
|
||||
*** Relative way
|
||||
|
||||
The relative way is a bit simpler, shorter and easier to say:
|
||||
|
||||
: biguha nulase fa bebe b fe gavoti.
|
||||
|
||||
In fact, this relative sentence can be made into an absolute sentence:
|
||||
|
||||
: biguha nulase fa bebe b fe gavoti do valo. valo.
|
||||
|
||||
*** Notes
|
||||
|
||||
In speech the relative way is much more useful than the absolute one. Both are
|
||||
useful, though.
|
||||
|
||||
|
||||
** Identifiers
|
||||
|
||||
Some of the groups can be used as identifiers. When an identifier is used one
|
||||
or more arguments are expected. The integer identifier requires one argument
|
||||
(the number), the real number identifier requires two arguments (before and
|
||||
after the point), and the letter identifier requires one argument. To use a
|
||||
group as an identifier, prefix it with *FA*.
|
||||
|
||||
** Numbers
|
||||
|
||||
Numbers in Na are duodecimal, i.e. base 12. The alphabet is used as numbers. A
|
||||
is used for zero, the consonants range from 1 to 10, and O is used for 11. When
|
||||
specifying a number, it should be prefixed with *FA BEBA* (real numbers) or any
|
||||
other name from a subclassed number identifier, and it should be written with
|
||||
the least important bit first (LSB). To pronounce a number, speak the letters
|
||||
of the number one by one.
|
||||
|
||||
Examples:
|
||||
|
||||
+ FA BEBE GB = 16
|
||||
+ FA BEBE D = 2
|
||||
+ FA BEBA D AT = 2.108
|
||||
|
||||
TODO: Improve this strange system
|
||||
|
||||
|
||||
** Example 2: We transported the ship into another dimension
|
||||
|
||||
This sentence is a bit tricky. We start by splitting the sentence into
|
||||
meaningful parts:
|
||||
|
||||
+ we transport (in the past)
|
||||
+ <something specific> ship
|
||||
+ into
|
||||
+ another dimension
|
||||
|
||||
Again, base words have not been defined yet, so we assume that "we (generic)"
|
||||
(we do not know if it is an exclusive or inclusive we) is GELO, "transport" is
|
||||
LOLOTI, the past is BATATO, something specific is SESE, "ship" is MOLOTE,
|
||||
"into" is NIKO, "another" is KOBO, and "dimension" is TILE.
|
||||
|
||||
It appears that it is actually quite easy to create a relative sentence now:
|
||||
|
||||
: batato gelo loloti fe sese molote niko fe fe tile kobo.
|
||||
|
||||
Notice the two FE in the end. Without the second FE, the sentence could also
|
||||
mean "We transported another dimension into the ship.". It would not be wrong
|
||||
to omit the FE, but it would create an ambigious sentence (which can be
|
||||
useful).
|
||||
|
||||
Remember that the following sentence means excactly the same as the previous:
|
||||
|
||||
: loloti batato gelo fe niko molote sese fe fe kobo tile.
|
||||
|
||||
Word order is only important in the case of identifiers and their arguments.
|
||||
|
||||
|
||||
** Example 3: 33+2.4i
|
||||
|
||||
33+2.4i is a complex number. The x+yi notation doesn't fit well in Na. Instead,
|
||||
the *FA BEDA* identifier is used (33+2.4i = 33.0+2.4i):
|
||||
|
||||
: fa beda td a d g.
|
||||
|
||||
Again, this is not perfect.
|
||||
|
||||
|
||||
** TODO Foreign words
|
||||
|
||||
Foreign words present a problem in Na.
|
||||
|
||||
|
||||
** TODO Built-ins
|
||||
|
||||
~1000 words needed to begin with.
|
||||
|
||||
|
||||
** Miscellaneous
|
||||
|
||||
Since there are only 16 characters (14 letters, the period, and space), one
|
||||
character can be stored in only 4 bits, and 2 characters can be stored in one
|
||||
byte.
|
||||
|
||||
Because of the infinitely many relatively different ways to say the same thing,
|
||||
texts and speech can be varied a great deal. This could be quite useful in
|
||||
e.g. poems.
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
#+title: Number bases
|
||||
#&summary
|
||||
This is fairly serious.
|
||||
#&
|
||||
#+license: wtfpl
|
||||
|
||||
| Base | Description |
|
||||
|-----------------------+----------------------------------------------------|
|
||||
| u-nary | the always true base |
|
||||
| bi-nary | the somewhat true base |
|
||||
| tri-nary | hipster binary ("binary is so mainstream") |
|
||||
| revolutio-nary | trinary instead of binary |
|
||||
| counterrevolutio-nary | binary |
|
||||
| imagi-nary | unary imagined to be useful |
|
||||
| visio-nary | binary or trinary, depending on the person |
|
||||
| statio-nary | trinary or binary, depending on the person |
|
||||
| ordi-nary | base 10 ("this works, so why use something else?") |
|
||||
| extraordi-nary | base 11 |
|
||||
| veteri-nary | base 14 ("Tetra? Is that an animal?") |
|
||||
| no-nary | unary |
|
||||
| u-r-i-nary | binary (mind melt) |
|
||||
| evolutio-nary | base 60 |
|
||||
| arbitr-ary | whatever |
|
||||
@@ -1,377 +0,0 @@
|
||||
#+title: Old junk code: Word finder
|
||||
#+summary: Less than perfect C code
|
||||
#+license: wtfpl, unless otherwise noted
|
||||
#+startup: showall
|
||||
#&toc
|
||||
|
||||
|
||||
* Old junk code: Word finder
|
||||
|
||||
#+caption: Based on [[https://commons.wikimedia.org/wiki/File:2001-91-1_Computer,_Laptop,_Pentagon_(5891422370).jpg][this]], CC BY 2.0
|
||||
#&img;url=sadcomputer.png, float=right
|
||||
|
||||
If you ever get tired of looking at your own junk code, take a look at this.
|
||||
|
||||
In August 2008, when I was still learning to program in C, I created a program
|
||||
"ordfinder" (eng: word finder) which, given a word and a dictionary, prints the
|
||||
words from the dictionary which can be created from the letters from the given
|
||||
word in any order. Incredibly, it ended up compiling and works perfectly for any
|
||||
word whose length does not exceed 8 characters, although it is a bit slow.
|
||||
|
||||
But why not more than 8 characters? My view of memory might have been a bit
|
||||
naive back then, because the first step in my algorithm is to generate and
|
||||
store all permutations of all subsequences of the given word. That is, if the
|
||||
string is "me", my program stores the array ={ "m", "e", "me", "em" }= in
|
||||
memory before going on to reading the dictionary and looking for matches.
|
||||
|
||||
If the string is "you", the program stores ={ "y", "o", "yo", "oy", "u", "yu",
|
||||
"uy", "ou", "uo", "you", "yuo", "oyu", "ouy", "uyo", "uoy" }=.
|
||||
|
||||
If the string is "computer", the program stores the 109600 permutations of the
|
||||
subsequences of "computer".
|
||||
|
||||
If the string is "difficult", the length of 9 characters means that the program
|
||||
attempts to store 986409 strings of lengths 1 to 9. That probably takes up not
|
||||
more than 10 MB, so it shouldn't be a problem. However, my program seems to
|
||||
store the list of words on the stack instead of in memory, so words with length
|
||||
9 or above cause a stack overflow to happen.
|
||||
|
||||
In any case, a word length of 10 would require about 100 MB, a word length of 11
|
||||
about 1.2 GB, a word length of 12 about 15.6 GB, and a word length of 17 (like
|
||||
"inconspicuousness") about 16,5 Petabytes (16500000 GB). That's 6,5 Petabytes
|
||||
*more* than [[http://archive.org/web/petabox.php][what the Internet Archive uses]] to store millions of websites, books,
|
||||
video and audio.
|
||||
|
||||
So perhaps neither my algorithm nor my implementation was that good.
|
||||
|
||||
|
||||
* The code
|
||||
|
||||
Note that this code doesn't actually compile, because of all the wrong
|
||||
code. However, it did compile back in 2008 which means that either I added the
|
||||
wrong code after I had compiled it, or I used an overfriendly compiler (I don't
|
||||
remember which compiler it was, but it ran on Windows). I have run the old
|
||||
executable with ~wine~, and that works.
|
||||
|
||||
It's not necesarry to know C to laugh at this code, but it helps.
|
||||
|
||||
We'll start with some basic ~#include~s.
|
||||
|
||||
#+BEGIN_SRC c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#+END_SRC
|
||||
|
||||
So far, so good. Then the global variables with descriptive names. And let's
|
||||
declare four strings of length 0 to be statically allocated, because we'll just
|
||||
extend them later on...?
|
||||
|
||||
#+BEGIN_SRC c
|
||||
char os[0],s[0],r[0],t[0];
|
||||
int l,c,rc,k,sk,i,ii,iii,ri;
|
||||
#+END_SRC
|
||||
|
||||
The next step is to define our own version of C's builtin ~strstr~ function
|
||||
(almost). I was used to PHP, so I wanted the same return values as PHP's
|
||||
~strpos~.
|
||||
|
||||
#+BEGIN_SRC c
|
||||
int strpos (const char *haystack, const char *needle) {
|
||||
int i;
|
||||
|
||||
if (strlen (haystack) < strlen (needle))
|
||||
return -1;
|
||||
|
||||
for (i = 0; i <= (strlen (haystack) - strlen(needle)); i++) {
|
||||
if (!strncmp (&haystack[i], needle, strlen(needle)))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
Then it's time for the main function. We don't want to separate it into
|
||||
auxiliary functions, because that's just ugly!
|
||||
|
||||
Indentation? Too much wastes too much space.
|
||||
|
||||
#+BEGIN_SRC c
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc>1) {
|
||||
strcpy(os,argv[1]);
|
||||
}
|
||||
else {
|
||||
printf("Indtast ord: ");
|
||||
gets(os);
|
||||
}
|
||||
printf("T\x91nker...\n");
|
||||
strcpy(s,os);
|
||||
for(i=0;s[i];i++) {
|
||||
s[i]=tolower(s[i]);
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
Wait, what? We use ~strcpy~ to copy the string ~argv[1]~, which contains the
|
||||
word we want to permute, into the statically allocated ~os~ with length 0? Or we
|
||||
read a line from standard in and save in ~os~? And almost the same for ~s~?
|
||||
That's... not good.
|
||||
|
||||
At least these two lines aren't that bad.
|
||||
|
||||
#+BEGIN_SRC c
|
||||
l=strlen(s);
|
||||
c=pow(l,l);
|
||||
#+END_SRC
|
||||
|
||||
But then begins the actual permutation generation logic. I have tried to
|
||||
re-understand it, with no success.
|
||||
|
||||
#+BEGIN_SRC c
|
||||
rc=1;
|
||||
i=0;
|
||||
while (i<l-1) {
|
||||
rc=rc*(l-i);
|
||||
i++;
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
While we're at it, why not declare two to-be-statically-allocated arrays with
|
||||
dynamically-generated ints as lengths?
|
||||
|
||||
#+BEGIN_SRC c
|
||||
int ca[l];
|
||||
char ra[rc][l+1];
|
||||
#+END_SRC
|
||||
|
||||
And then some more assignments and ~while~ loops...
|
||||
|
||||
#+BEGIN_SRC c
|
||||
ri=0;
|
||||
i=0;
|
||||
while (i<c) {
|
||||
k=1;
|
||||
ii=0;
|
||||
while (ii<l && k==1) {
|
||||
#+END_SRC
|
||||
|
||||
This formula does something. I'm not sure what.
|
||||
|
||||
#+BEGIN_SRC c
|
||||
ca[ii]=floor(i/pow(l,l-ii-1))-floor(i/pow(l,l-ii))*l;
|
||||
#+END_SRC
|
||||
|
||||
More ~while~ loops, now also with ~if~ statements.
|
||||
|
||||
#+BEGIN_SRC c
|
||||
iii=0;
|
||||
while (iii<ii) {
|
||||
if (ca[ii]==ca[iii]) {k=0;}
|
||||
iii++;
|
||||
}
|
||||
ii++;
|
||||
}
|
||||
if (k==1) {
|
||||
strcpy(ra[ri],"");
|
||||
ii=0;
|
||||
while (ii<l) {
|
||||
strncpy(t,s+ca[ii],1);
|
||||
#+END_SRC
|
||||
|
||||
Let's concatenate ~t~ onto ~ra[ri]~, a string which hardly exists due to the
|
||||
~char ra[rc][l+1];~ magic above.
|
||||
|
||||
#+BEGIN_SRC c
|
||||
strcat(ra[ri],t);
|
||||
ii++;
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
And why not concatenate an end-of-string mark onto a string which, if it
|
||||
doesn't have an end-of-string mark, will make ~strcat~ fail miserably?
|
||||
|
||||
#+BEGIN_SRC c
|
||||
strcat(ra[ri],"\0");
|
||||
#+END_SRC
|
||||
|
||||
And then more junk.
|
||||
|
||||
#+BEGIN_SRC c
|
||||
sk=1;
|
||||
ii=0;
|
||||
while (ii<ri && sk==1) {
|
||||
if (strcmp(ra[ri],ra[ii])==0) {sk=0;}
|
||||
ii++;
|
||||
}
|
||||
if (sk==1) {
|
||||
//printf("%s\n",ra[ri]);
|
||||
ri++;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
//printf("\nOrd: %s\nOrdl\x91ngde: %d\nOrdkombinationer: %d\n",os,l,ri);
|
||||
#+END_SRC
|
||||
|
||||
Phew... At this point, I'm certain that ~ra~ is supposed to be an array of all
|
||||
word permutations. So let's open our dictionary "ord.txt" and look for matches.
|
||||
|
||||
#+BEGIN_SRC c
|
||||
FILE *f;
|
||||
char wrd[128];
|
||||
if (f=fopen("ord.txt","r")) {
|
||||
FILE *fw;
|
||||
#+END_SRC
|
||||
|
||||
Everything is written both to output.txt *and* standard out. Anything else would
|
||||
be stupid.
|
||||
|
||||
#+BEGIN_SRC c
|
||||
fw=fopen("output.txt","w");
|
||||
printf("Ord dannet af \"%s\":\n\n",os);
|
||||
fprintf(fw,"Ord dannet af \"%s\":\n\n",os);
|
||||
int wc=0;
|
||||
while(!feof(f)) {
|
||||
if(fgets(wrd,126,f)) {
|
||||
#+END_SRC
|
||||
|
||||
The words each end with a newline, so let's replace the newline with an
|
||||
end-of-string mark.
|
||||
|
||||
#+BEGIN_SRC c
|
||||
wrd[strlen(wrd)-1]=0;
|
||||
//printf("%s\n",wrd);
|
||||
k=0;
|
||||
ii=0;
|
||||
while (ii<ri && k==0) {
|
||||
#+END_SRC
|
||||
|
||||
The magical core of the matching logic, using our own ~strpos~:
|
||||
|
||||
#+BEGIN_SRC c
|
||||
if (strpos(ra[ii],wrd)>-1) {k=1;}
|
||||
#+END_SRC
|
||||
|
||||
If ~k == 1~, something good happens. But it doesn't happen at once for some
|
||||
reason.
|
||||
|
||||
#+BEGIN_SRC c
|
||||
ii++;
|
||||
}
|
||||
if (k==1) {
|
||||
printf("%s\n",wrd);
|
||||
fprintf(fw,"%s\n",wrd);
|
||||
wc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\nI alt %d ord\n",wc);
|
||||
fprintf(fw,"\nI alt %d ord",wc);
|
||||
fclose(fw);
|
||||
fclose(f);
|
||||
system("output.txt");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
And that's my pretty C code.
|
||||
|
||||
|
||||
* The SML equivalent
|
||||
|
||||
To make my inefficient algorithm a bit clearer, I have made a few SML functions
|
||||
to do the same as above:
|
||||
|
||||
#+BEGIN_SRC ocaml
|
||||
open List
|
||||
|
||||
(* Removes an element from a list. *)
|
||||
fun remove x (y :: ys) = if x = y
|
||||
then ys
|
||||
else y :: remove x ys
|
||||
|
||||
(* Tails of a list. Stolen from Haskell's Data.List. *)
|
||||
fun tails [] = [[]]
|
||||
| tails (xxs as (_ :: xs)) = xxs :: tails xs
|
||||
|
||||
(* Non-empty subsequences of a list. Stolen from Haskell's Data.List. *)
|
||||
fun nonEmptySubsequences [] = []
|
||||
| nonEmptySubsequences (x :: xs) =
|
||||
let
|
||||
fun f (ys, r) = ys :: (x :: ys) :: r
|
||||
in
|
||||
[x] :: foldr f [] (nonEmptySubsequences xs)
|
||||
end
|
||||
|
||||
(* All permutations of a list. *)
|
||||
fun permutations [] = [[]]
|
||||
| permutations xs =
|
||||
let
|
||||
fun subPermutations x = map (fn ys => x :: ys) (permutations (remove x xs))
|
||||
in
|
||||
concat (map subPermutations xs)
|
||||
end
|
||||
|
||||
|
||||
(* Permutations of subsequences of a list. *)
|
||||
fun subsequencePermutations xs = concat (map permutations (nonEmptySubsequences xs))
|
||||
|
||||
(* The same, but for a string. *)
|
||||
fun stringSubsequencePermutations s = map implode (subsequencePermutations (explode s))
|
||||
|
||||
(* Finds words in `wordList` which matches any permutation of any subsequence
|
||||
* of `word`. *)
|
||||
fun findMatchingWords word wordList =
|
||||
let
|
||||
val wordPermutations = stringSubsequencePermutations word
|
||||
in
|
||||
filter (fn testWord =>
|
||||
exists (fn word => word = testWord)
|
||||
wordPermutations) wordList
|
||||
end
|
||||
#+END_SRC
|
||||
|
||||
As well as some SML functions to calculate the number of permutations and bytes:
|
||||
|
||||
#+BEGIN_SRC ocaml
|
||||
(* Calculates the factorial. *)
|
||||
fun factorial 0 = 1
|
||||
| factorial n = n * factorial (n - 1)
|
||||
|
||||
(* Calculates the binomial coeffecient. *)
|
||||
fun binomc n k = factorial n div (factorial k * factorial (n - k))
|
||||
|
||||
(* Gives [m, m + 1, ..., n]. *)
|
||||
fun upTo m n = if m < n
|
||||
then m :: upTo (m + 1) n
|
||||
else [m]
|
||||
|
||||
(* Gives the total number of word subsequence permutations for a given word
|
||||
* length. *)
|
||||
fun nPermutations len = foldl op+ 0 (map (fn n => factorial n * binomc len n)
|
||||
(upTo 1 len))
|
||||
|
||||
(* Gives the size in bytes for storing all word subsequence permutations for a
|
||||
* given word length in a space-saving way: there are ~len~ arrays, each taking
|
||||
* up space for the pointer to the array and the permutations of subsequences of
|
||||
* length n where ~1 <= n <= len~ and n is unique.
|
||||
*)
|
||||
fun nSize len = 8 * len + foldl op+ 0 (
|
||||
map (fn n => (n + 1) * factorial n * binomc len n)
|
||||
(upTo 1 len))
|
||||
#+END_SRC
|
||||
|
||||
* The alternative
|
||||
|
||||
Preprocess the dictionary into a clever data structure and don't use up all the
|
||||
memory.
|
||||
|
||||
|
||||
#&line
|
||||
|
||||
Originally published [[http://dikutal.dk/artikler/old-junk-code-word-finder][here]].
|
||||
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 50 KiB |
@@ -1,110 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.1//EN'
|
||||
'http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd'>
|
||||
<html version='-//W3C//DTD XHTML 1.1//EN'
|
||||
xmlns='http://www.w3.org/1999/xhtml'
|
||||
xml:lang='en'
|
||||
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
|
||||
xsi:schemaLocation='http://www.w3.org/1999/xhtml
|
||||
http://www.w3.org/MarkUp/SCHEMA/xhtml11.xsd'>
|
||||
<head>
|
||||
<title>POTATORRS!!!CTRLONEOOPSSHIFTONESHIFTONE</title>
|
||||
<meta name='author' content='Niels Serup' />
|
||||
<meta name='description'
|
||||
content='It is imperative that you do not approach the Potators!' />
|
||||
<meta name='keywords'
|
||||
content='potator' />
|
||||
<link rel='schema.DCTERMS' href='http://purl.org/dc/terms/' />
|
||||
<meta name='DCTERMS.creator' content='Niels Serup' />
|
||||
<meta name='DCTERMS.language' content=en />
|
||||
<meta name='DCTERMS.audience' content='general public' />
|
||||
<meta name='robots' content='ALL' />
|
||||
<style type='text/css'>
|
||||
.warning {
|
||||
background-color: #fe93cc;
|
||||
text-decoration: blink;
|
||||
}
|
||||
|
||||
p {
|
||||
background-color: #ccfe93;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id='wrapper'>
|
||||
<div style='float: right; width: 400px;'>
|
||||
<img src='img/001.jpg' alt='really, really angry potator'
|
||||
style='width: 400px;' />
|
||||
<img src='img/002.jpg' alt='angry potator' style='width: 400px;'/>
|
||||
<img src='img/000.jpg' alt='really, really angry potator'
|
||||
style='width: 400px;' />
|
||||
</div>
|
||||
<h1 class='warning'>ATTENTION!</h1>
|
||||
<p>
|
||||
As the invasion drew nearer, Master Potator Pozrundarhan envisioned the
|
||||
perfect future. At that very point, 15 years ago, Earth was doomed.
|
||||
</p>
|
||||
<p>
|
||||
NOW THE TIME FOR POTATOR DOMINION HAS COME! JOIN THE POTATORRS OR BE
|
||||
ENSLAVED!
|
||||
</p>
|
||||
<h2>Origins</h2>
|
||||
<p>
|
||||
It is a fact that most humans have five fingers on their left hand. It
|
||||
is a fact that five is a prime number. It is a fact that prime numbers
|
||||
are special. It is a fact that potators are special. It is a fact that
|
||||
potators dominate prime numbers. It is a fact that potators dominate
|
||||
the world.
|
||||
</p>
|
||||
<h1>FJUTURE</h1>
|
||||
<p>
|
||||
To look at the future, one must look at the past. To look at the past,
|
||||
one must look at the present. To look at the present, one must look at
|
||||
the future.
|
||||
To look at the future, one must look at the past. To look at the past,
|
||||
one must look at the present. To look at the present, one must look at
|
||||
the future.
|
||||
To look at the future, one must look at the past. To look at the past,
|
||||
one must look at the present. To look at the present, one must look at
|
||||
the future.
|
||||
To look at the future, one must look at the past. To look at the past,
|
||||
one must look at the present. To look at the present, one must look at
|
||||
the future.
|
||||
To look at the future, one must look at the past. To look at the past,
|
||||
one must look at the present. To look at the present, one must look at
|
||||
the future.
|
||||
To look at the future, one must look at the past. To look at the past,
|
||||
one must look at the present. To look at the present, one must look at
|
||||
the future.
|
||||
To look at the future, one must look at the past. To look at the past,
|
||||
one must look at the present. To look at the present, one must look at
|
||||
the <strong>POTATORS</strong>.
|
||||
</p>
|
||||
<h2>THE Potators</h2>
|
||||
<p>
|
||||
A mix of wisdom an evil, they roam the skies in custom-built sky
|
||||
ships. They <em>are</em> dangerous.
|
||||
</p>
|
||||
<h2>BIBle</h2>
|
||||
<ol>
|
||||
<li>Rules with an index n where n > 1 are not valid</li>
|
||||
<li>This rule is not valid.</li>
|
||||
<li>This rule is not undefined.</li>
|
||||
<li>Do not not murder non-potators</li>
|
||||
<li>Do make sense</li>
|
||||
</ol>
|
||||
<h3>No more TEXT</h3>
|
||||
<p>
|
||||
POTATORRS INVADE THEY DO NOT WRITE!
|
||||
</p>
|
||||
<p>
|
||||
This Artificially Authorized Article and its groundbreaking pictures
|
||||
are available under the Do What The Fuck You Want To Public License
|
||||
(WTFPL) 2.0.
|
||||
</p>
|
||||
<p>
|
||||
<a href='http://hvy.metanohi.name/potators/'>High-quality pictures of POTATORS</a>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,13 +0,0 @@
|
||||
#+title: Profeten, doktoren og videnskabsmanden
|
||||
#&summary
|
||||
A story
|
||||
#&
|
||||
#+license: wtfpl
|
||||
|
||||
* Profeten, doktoren og videnskabsmanden
|
||||
|
||||
"Profeten, doktoren og videnskabsmanden" ("The Prophet, the Doctor and the
|
||||
Scientist") is a short nonsensical story in Danish by Niels. It is available
|
||||
under CC BY-SA 3.0+ as an A5-sized pdf.
|
||||
|
||||
<@html <a href='pvd.pdf'>Download.<br /><img src='p1.png' alt='Front page' /></a>@>
|
||||
|
Before Width: | Height: | Size: 442 KiB |
@@ -1,113 +0,0 @@
|
||||
#+title: Combining PyGame and PyCairo
|
||||
#&summary
|
||||
How to combine two Pythonic graphical frameworks
|
||||
#&
|
||||
#+license: wtfpl
|
||||
|
||||
* Combining PyGame and PyCairo
|
||||
|
||||
#&+classes=note
|
||||
See [[http://pygame.org/wiki/CairoPygame]] for other examples.
|
||||
#&
|
||||
|
||||
This piece of code allows you to convert a Cairo surface to a PyGame
|
||||
surface. It also includes a small example on how to make SVG loading work. It
|
||||
works with Python 2.5+ and requires relatively recent versions of pygame,
|
||||
pycairo and NumPy to work. For the SVG example to work, you must also have rsvg
|
||||
installed.
|
||||
|
||||
#+BEGIN_SRC python2
|
||||
#!/usr/bin/env python
|
||||
# Copyleft 2010 Niels Serup, WTFPL 2.0. Free software.
|
||||
|
||||
### Imports ###
|
||||
import math
|
||||
import pygame
|
||||
import cairo
|
||||
import numpy
|
||||
import Image
|
||||
|
||||
### Constants ###
|
||||
width, height = 640, 480
|
||||
|
||||
|
||||
### Functions ###
|
||||
def draw(ctx):
|
||||
ctx.set_line_width(15)
|
||||
ctx.arc(320, 240, 200, 0, 2 * math.pi)
|
||||
|
||||
# r g b a
|
||||
ctx.set_source_rgba(0.6, 0, 0.4, 1)
|
||||
ctx.fill_preserve()
|
||||
|
||||
# r g b a
|
||||
ctx.set_source_rgba(0, 0.84, 0.2, 0.5)
|
||||
ctx.stroke()
|
||||
|
||||
def bgra_surf_to_rgba_string(cairo_surface):
|
||||
# We use PIL to do this
|
||||
img = Image.frombuffer(
|
||||
'RGBA', (cairo_surface.get_width(),
|
||||
cairo_surface.get_height()),
|
||||
cairo_surface.get_data(), 'raw', 'BGRA', 0, 1)
|
||||
|
||||
return img.tostring('raw', 'RGBA', 0, 1)
|
||||
|
||||
|
||||
### Body ###
|
||||
# Init PyGame
|
||||
pygame.display.init()
|
||||
screen = pygame.display.set_mode((width, height), 0, 32)
|
||||
|
||||
# Create raw surface data (could also be done with something else than
|
||||
# NumPy)
|
||||
data = numpy.empty(width * height * 4, dtype=numpy.int8)
|
||||
|
||||
# Create Cairo surface
|
||||
cairo_surface = cairo.ImageSurface.create_for_data(
|
||||
data, cairo.FORMAT_ARGB32, width, height, width * 4)
|
||||
|
||||
# Draw with Cairo on the surface
|
||||
ctx = cairo.Context(cairo_surface)
|
||||
draw(ctx)
|
||||
|
||||
|
||||
##### SVG LOADING EXAMPLE #####
|
||||
# Using rsvg it is possible to render an SVG file onto a Cairo
|
||||
# surface. Uncomment the following lines to make it work.
|
||||
#import rsvg # This will probably not work in Windows. As far as I
|
||||
# know, only GNU/Linux distibutions package this Python
|
||||
# module. Nevertheless, it should be easy to create a small wrapper;
|
||||
# see http://www.cairographics.org/cairo_rsvg_and_python_in_windows/
|
||||
|
||||
# Load the file
|
||||
#svg_graphics = rsvg.Handle('path/to/file.svg')
|
||||
|
||||
# Render the graphics onto your Cairo context
|
||||
#svg_graphics.render_cairo(ctx)
|
||||
|
||||
# To get the SVG file's dimensions before you create a Cairo surface,
|
||||
# use the following function:
|
||||
#print svg_graphics.get_dimension_data()
|
||||
###############################
|
||||
|
||||
# On little-endian machines (and perhaps big-endian, who knows?),
|
||||
# Cairo's ARGB format becomes a BGRA format. PyGame does not accept
|
||||
# BGRA, but it does accept RGBA, which is why we have to convert the
|
||||
# surface data. You can check what endian-type you have by printing
|
||||
# out sys.byteorder
|
||||
data_string = bgra_surf_to_rgba_string(cairo_surface)
|
||||
|
||||
# Create PyGame surface
|
||||
pygame_surface = pygame.image.frombuffer(
|
||||
data_string, (width, height), 'RGBA')
|
||||
|
||||
# Show PyGame surface
|
||||
screen.blit(pygame_surface, (0,0))
|
||||
pygame.display.flip()
|
||||
|
||||
clock = pygame.time.Clock()
|
||||
while not pygame.QUIT in [e.type for e in pygame.event.get()]:
|
||||
clock.tick(30)
|
||||
#+END_SRC
|
||||
|
||||
@@ -1,293 +0,0 @@
|
||||
#+title: Sound Programming
|
||||
#+summary: Programming sound in Live-Sequencer and ChucK
|
||||
#+license: wtfpl, unless otherwise noted
|
||||
#+startup: showall
|
||||
#&toc
|
||||
|
||||
* Sound Programming
|
||||
|
||||
Much can be programmed, and that includes sound. In the digital world, sound is
|
||||
typically represented by sequences of about 90 kB per second, so "printing"
|
||||
sound is merely a matter of printing bytes. As such, any general purpose
|
||||
language can be used to generate sounds.
|
||||
|
||||
However, it's boring to create a program that does nothing but print bytes, and
|
||||
it's potentially difficult to make those bytes sound nice; we want abstractions
|
||||
to simplify matters for us: instruments, drums, musical notes, and a high-level
|
||||
program structure. Many programming languages have good libraries that allow us
|
||||
to achieve just that, but to keep it simple we'll focus on how to program sound
|
||||
in two languages designed to output sound: ChucK and Live-Sequencer.
|
||||
|
||||
Let's create some sounds.
|
||||
|
||||
|
||||
* The square wave
|
||||
|
||||
We'll start with ChucK and a small square wave program:
|
||||
|
||||
#+BEGIN_SRC c
|
||||
// Connect a square oscillator to the sound card.
|
||||
SqrOsc s => dac;
|
||||
|
||||
// Set its frequency to 440 Hz.
|
||||
440 => s.freq;
|
||||
|
||||
// Lower the volume.
|
||||
0.1 => s.gain;
|
||||
|
||||
// Let it run indefinitely.
|
||||
while (true) {
|
||||
1000::second => now;
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
ChucK is an imperative language. Instructions on how to install and run it can
|
||||
be found on its [[http://chuck.cs.princeton.edu/][website]], along with other useful information. You can listen to
|
||||
the above sound [[square.flac][here]].
|
||||
|
||||
To do the same in Live-Sequencer, we must find a square wave "instrument" and use
|
||||
that.
|
||||
|
||||
#+BEGIN_SRC haskell
|
||||
module SquareWave where
|
||||
|
||||
-- Basic imports.
|
||||
import Prelude
|
||||
import List
|
||||
import Midi
|
||||
import Instrument
|
||||
import Pitch
|
||||
|
||||
-- The function "main" is run when the program is run.
|
||||
-- It returns a list of MIDI actions.
|
||||
main = concat [ program lead1Square -- Use a square wave instrument.
|
||||
, cycle ( -- Keep playing the following forever.
|
||||
note 1000000 (a 4) -- Play 1000000 milliseconds of the musical note A4
|
||||
) -- about 440 Hz.
|
||||
]; -- End with a semicolon.
|
||||
#+END_SRC
|
||||
|
||||
Live-Sequencer differs from ChucK in that it is functional, but another major
|
||||
difference is that while ChucK (in general) generates raw sound bytes,
|
||||
Live-Sequencer generates so-called MIDI codes, which another program converts to
|
||||
the actual audio. Live-Sequencer has a couple of funky features such as
|
||||
highlighting which part of one's program is played; read about it and how to
|
||||
install and run it at [[http://www.haskell.org/haskellwiki/Live-Sequencer][this wiki]]. You can listen to the above sound [[squarewave.flac][here]].
|
||||
|
||||
|
||||
* Something more advanced
|
||||
|
||||
Let's try to create a small piece of music which can be expressed easily in
|
||||
Live-Sequencer (listen [[melodyexample.flac][here]]):
|
||||
|
||||
#+BEGIN_SRC haskell
|
||||
module MelodyExample where
|
||||
|
||||
import Prelude
|
||||
import List
|
||||
import Midi
|
||||
import Instrument
|
||||
import Pitch
|
||||
|
||||
-- Durations (in milliseconds).
|
||||
en = 100;
|
||||
qn = 2 * en;
|
||||
hn = 2 * qn;
|
||||
wn = 2 * hn;
|
||||
|
||||
twice x = concat [x, x];
|
||||
|
||||
main = cycle rpgMusic;
|
||||
|
||||
rpgMusic = concat [ partA g
|
||||
, [Wait hn]
|
||||
, twice (partB [b, d])
|
||||
, partB [a, c]
|
||||
, partA b
|
||||
];
|
||||
|
||||
partA t = concat [ program frenchHorn
|
||||
, mel2 c e 4
|
||||
, mel2 c e 5 -- The '=:=' operator merges two lists of actions
|
||||
=:= -- so that they begin simultaneously.
|
||||
(concat [ [Wait wn]
|
||||
, mel2 d t 3
|
||||
])
|
||||
];
|
||||
|
||||
partB firsts = concat [ program trumpet
|
||||
, concat (map mel0 [c, e])
|
||||
=:=
|
||||
mergeMany (map mel1 firsts)
|
||||
];
|
||||
|
||||
-- Instrument-independent melodies.
|
||||
mel0 x = concat [ note wn (x 3)
|
||||
, note hn (x 4)
|
||||
, note en (x 2)
|
||||
, [Wait wn]
|
||||
, twice (note qn (x 2))
|
||||
];
|
||||
|
||||
mel1 x = concat [ note (wn + hn) (x 5)
|
||||
, note (hn + qn) (x 4)
|
||||
];
|
||||
|
||||
mel2 x y n = concat [ twice (note qn (x 3))
|
||||
, concatMap (note hn . y) [3, 4, 4]
|
||||
, note wn (x n) =:= note wn (y n)
|
||||
];
|
||||
#+END_SRC
|
||||
|
||||
When you play the program from the Live-Sequencer GUI, the code in use is
|
||||
highlighted:
|
||||
|
||||
#&img;url=sound-highlight.png, width=640, center, caption=Highlighting of sound, screenshot
|
||||
|
||||
The same could be expressed in ChucK, but the comparison wouldn't be fair. While
|
||||
Live-Sequencer is designed for describing melodies, ChucK's purpose is sound
|
||||
synthesis, which is more general. We'll create something more fitting of ChucK's
|
||||
capabilities, while still focusing on the use of instruments (listen [[more_advanced.flac][here]]):
|
||||
|
||||
#+BEGIN_SRC c
|
||||
// Background music for an old sci-fi horror B movie.
|
||||
|
||||
// Filters.
|
||||
Gain g;
|
||||
NRev reverb;
|
||||
|
||||
// Connect the Gain to the sound card.
|
||||
g => dac;
|
||||
|
||||
// Connect the data sent to the sound card through the reverb filter back to the
|
||||
// sound card.
|
||||
adc => reverb => dac;
|
||||
|
||||
// Instruments.
|
||||
Mandolin mandolin;
|
||||
0.2 => mandolin.gain;
|
||||
Sitar sitar;
|
||||
0.8 => sitar.gain;
|
||||
Moog moog;
|
||||
|
||||
// Instrument connections to the Gain.
|
||||
mandolin => g;
|
||||
sitar => g;
|
||||
moog => reverb => g;
|
||||
|
||||
// Play a frequency 'freq' for duration 'dura' on instrument 'inst'.
|
||||
fun void playFreq(StkInstrument inst, dur dura, int freq) {
|
||||
freq => inst.freq; // Set the frequency.
|
||||
0.1 => inst.noteOn; // Start playing with a velocity of 0.1.
|
||||
dura => now;
|
||||
0.1 => inst.noteOff; // Stop playing.
|
||||
}
|
||||
|
||||
// Play a melody.
|
||||
fun void a_melody(StkInstrument inst, int freq_offset) {
|
||||
int i;
|
||||
|
||||
// Fork the command to play "in the background".
|
||||
spork ~ playFreq(moog, 600::ms, 400 - freq_offset);
|
||||
|
||||
for (0 => i; i < 3; i++) {
|
||||
playFreq(inst, 200::ms, 220 + freq_offset + 10 * i);
|
||||
}
|
||||
|
||||
// Create an array and use every element in it.
|
||||
[3, 4, 4, 5, 3] @=> int ns[];
|
||||
for (0 => i; i < ns.cap(); i++)
|
||||
{
|
||||
playFreq(inst, 100::ms, ns[i] * 132 + freq_offset);
|
||||
}
|
||||
}
|
||||
|
||||
// Infinite sound loop of pseudo-random frequencies.
|
||||
while (true) {
|
||||
spork ~ a_melody(moog, Math.random2(0, 30));
|
||||
Math.random2f(0.4, 0.9) => g.gain; // Adjust the gain.
|
||||
a_melody(mandolin, Math.random2(0, 350));
|
||||
a_melody(sitar, Math.random2(200, 360));
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
|
||||
* Algorithmic composition
|
||||
|
||||
Why not have the computer generate the melody as well as the sound? That
|
||||
*sounds* like a great idea!
|
||||
|
||||
Enter [[https: / / en.wikipedia.org / wiki / L-system][L-systems]]. An L-system has an alphabet and a set of rules, where each rule
|
||||
is used to transform the symbol on the left-hand side to the sequence of symbols
|
||||
on the right-hand side. We'll use this L-system to generate music:
|
||||
|
||||
#+BEGIN_SRC c
|
||||
-- Based on https://en.wikipedia.org/wiki/L-system#Example_7:_Fractal_plant
|
||||
Alphabet: X, F, A, B, P, M
|
||||
Rules:
|
||||
X -> FMAAXBPXBPFAPFXBMX
|
||||
F -> FF
|
||||
#+END_SRC
|
||||
|
||||
If we evaluate a L-system on a list, the system's rules are applied to each
|
||||
element in the list, and results are concatenated to make a new list. If we
|
||||
assign each symbol to a sequence of sounds and run the L-system a few times, we
|
||||
get [[lsystem.flac][this]].
|
||||
|
||||
#+BEGIN_SRC haskell
|
||||
module LSystem where
|
||||
|
||||
import Prelude
|
||||
import List
|
||||
import Midi
|
||||
import Instrument
|
||||
import Pitch
|
||||
|
||||
en = 100;
|
||||
qn = 2 * en;
|
||||
hn = 2 * qn;
|
||||
wn = 2 * hn;
|
||||
|
||||
-- Define the L-System.
|
||||
data Alphabet = X | F | A | B | P | M;
|
||||
expand X = [F, M, A, A, X, B, P, X, B, P, F, A, P, F, X, B, M, X];
|
||||
expand F = [F, F];
|
||||
expand _ = [];
|
||||
|
||||
-- Map different instruments to different channels.
|
||||
channelInsts = concat [ channel 0 (program celesta)
|
||||
, channel 1 (program ocarina)
|
||||
, channel 2 (program sitar)
|
||||
];
|
||||
|
||||
-- Define the mappings between alphabet and audio.
|
||||
interpret X = [Wait hn];
|
||||
interpret F = channel 0 (note qn (c 4));
|
||||
interpret A = channel 1 (note qn (a 5));
|
||||
interpret B = channel 1 (note qn (f 5));
|
||||
interpret P = channel 2 (note hn (a 3));
|
||||
interpret M = channel 2 (note hn (f 3));
|
||||
|
||||
-- A lazily evaluated list of all iterations.
|
||||
runLSystem expand xs = xs : runLSystem expand (concatMap expand xs);
|
||||
|
||||
-- The sound from a L-System.
|
||||
getLSystemSound expand interpret iterations start
|
||||
= concatMap interpret (runLSystem expand start !! iterations);
|
||||
|
||||
-- Use the third iteration of the L-System, and start with just X.
|
||||
main = channelInsts ++ getLSystemSound expand interpret 3 [X];
|
||||
#+END_SRC
|
||||
|
||||
Using an L-system is one of many ways to take composition to a high
|
||||
level. L-systems can be used to generate fractals, which are nice.
|
||||
|
||||
|
||||
* And so on
|
||||
|
||||
Many abstractions in sound generation allow for fun sounds to happen. Interested
|
||||
people might want to also take a look at e.g. [[http://haskell.cs.yale.edu/euterpea-2/][Euterpea]], [[http://puredata.info/][Pure Data]], or [[http://csounds.com/][Csound]].
|
||||
|
||||
#&line
|
||||
|
||||
Originally published [[http://dikutal.dk/artikler/sound-programming][here]].
|
||||
|
Before Width: | Height: | Size: 139 KiB |
@@ -1,172 +0,0 @@
|
||||
#+title: Stadig digital sikring mod gennemførsel af eksamen
|
||||
#&summary
|
||||
A text about the continuing failings of digital education and "copy
|
||||
protection". In Danish.
|
||||
#&
|
||||
#+license: wtfpl
|
||||
#+language: da
|
||||
|
||||
Jeg sendte denne besked til Undervisningsministeriet som så forklarede at de
|
||||
var nødt til at bruge kopisikring fordi de brugte tekst, billeder og video fra
|
||||
eksterne kilder (såsom BBC). Det må være muligt for dem at lave bedre aftaler i
|
||||
deres kraft af undervisningsministerium --- desuden er det ikke engang alle
|
||||
skoler der bruger de kopisikrede cd'er, så i flere tilfælde er kopisikring
|
||||
ligegyldig. Så fjern den dog!
|
||||
|
||||
Sendt 31. maj 2011. Se også <@eval macros.titlelink('digital-sikring')@>.
|
||||
|
||||
* Stadig digital sikring mod gennemførsel af eksamen
|
||||
|
||||
Hej UVM
|
||||
|
||||
D. 8. marts sendte jeg jer en klage/ideer-til-forbedring-e-mail ved navn
|
||||
"Digital sikring mod gennemførsel af eksamen en realitet" hvor jeg
|
||||
forklarede jer at kopisikringer på cd'er forhindrede min computer, som
|
||||
kører styresystemet GNU/Linux i stedet for fx Microsoft Windows eller
|
||||
Apple Mac OS X, i at læse teksten på cd'en til skriftlig engelsk
|
||||
terminsprøve (skriftlig engelsk eksamen 2010): videoklippene var
|
||||
tilgængelige i filsystemet, men teksten var der ikke. I skrev tilbage at
|
||||
I arbejdede på at det også skulle virke på GNU/Linux og at der
|
||||
sandsynligvis ikke ville være nogle problemer ved eksamen --- hvilket
|
||||
der så var. I går til skriftlig engelsk eksamen blev jeg endnu en gang
|
||||
ramt af cd-krypteringen, og kun skolens beredskab med en usb-stick
|
||||
reddede mig. Jeg kan acceptere at i sender cd'er ud, men vil I ikke nok
|
||||
lad være med at kopisikre dem? Det er både bedre og nemmere at lave
|
||||
ukrypterede cd'er.
|
||||
|
||||
Jeg ved ikke om dette er den rette kanal, men jeg vil lige beskrive mit
|
||||
problem på en teknisk måde og bevise min påstand om kopisikringen:
|
||||
|
||||
Først og fremmest: kravet til en computer til en skriftlig engelsk
|
||||
eksamen bør være at den understøtter basale standarder inden for tekst,
|
||||
lyd, video og, da I har valgt at bruge et webinterface, webteknologier
|
||||
såsom HTML, CSS og JavaScript. Dette betyder at computeren og det
|
||||
operativsystem der kører på den, skal have support for læsning af
|
||||
HTML-tekst m. CSS og JS der følger en HTML-standard, og systemet skal
|
||||
kunne dekode og afspille lyd og video der er gemt i standardiserede
|
||||
formater. Dette er alt. Man bør ikke stille flere krav.
|
||||
|
||||
GNU/Linux understøtter alle disse nødvendige standarder. Det samme kan
|
||||
ikke helt siges om MS Windows og Apple Mac, men det er muligt at få dem
|
||||
til at understøtte de få nødvendige standarder relativt nemt (selv om
|
||||
det er nemmere bare at skifte til GNU/Linux).
|
||||
|
||||
Men hvilke lyd- og videostandarder? Jeg undersøgte den videofil der
|
||||
fulgte med dette års eksamensoplæg, og jeg så at den brugte VP6 til
|
||||
video og MP3 til lyd. Disse to codecs er begge patenterede, og VP6 er
|
||||
tilmed proprietært. Dette betyder at folk ikke bare kan lave et nyt lyd-
|
||||
eller videoformat uden først at undersøge om bare en lillebitte del af
|
||||
deres format er en del af VP6, for hvis det er tilfældet, er der
|
||||
retssager og pengekrav. Softwarepatenter kan stoppe nogle vakse
|
||||
mennesker med at udvikle nye, revolutionerende computerprogrammer,
|
||||
algoritmer og digitale multimedieformater. Indrømmet, dette er kun
|
||||
direkte et problem i lande hvor softwarepatenter eksisterer, men i VP6's
|
||||
tilfælde er det samtidig også svært at implementere en dekoder da en
|
||||
fuld formatspecifikation med vilje ikke er gjort tilgængelig. Når folk
|
||||
bliver ved med at bruge disse patenterede formater, kan virksomheder
|
||||
føle sig tvunget til at bruge de samme formater, og de frie, bedre
|
||||
formater bliver usynlige. Så selv om EU og Danmark heldigvis ikke har
|
||||
softwarepatenter, bør vi stadig ikke bruger patenterede formater som VP6
|
||||
og MP3. Nogle hårdtarbejdene frivillige har sørget for at der er frie
|
||||
dekodere tilgængelige for VP6 og MP3, så jeg kunne godt se videoen ---
|
||||
det er bare ikke pointen. Formater man ikke kan kontrollere --- formater
|
||||
der bliver kontrolleret af en privat organisation --- bør ikke bruges,
|
||||
så digitalopfindere ikke begrænses af magtbaserede love.
|
||||
|
||||
Alternativet er formater som Ogg Theora eller VP8 for video og Ogg
|
||||
Vorbis, Ogg Speex eller FLAC for lyd. Funktionelt set er disse lige så
|
||||
gode --- eller bedre --- som fx VP6 og MP3, og samtidig er de frie. WebM
|
||||
er en ny "container" der består af VP8 for video og Vorbis for lyd. Den
|
||||
er nem at bruge i webbrowsere, og selv YouTube er begyndt at understøtte
|
||||
den.
|
||||
|
||||
Hvis man brugte WebM men stadig ville gøre det muligt for computere uden
|
||||
flere formater. Det har HTML5 fint support for. Og hvis ens browser ikke
|
||||
understøtter HTML5 --- hvilket er helt ok --- kan man have en Java
|
||||
fallback-player (ikke Flash).
|
||||
|
||||
Og nu til beviset at cd'en var kopisikret: På en brændt cd er der rå
|
||||
data. Denne rå data kan læses hvis man har en cd-læser. Den rå data er
|
||||
den samme uafhængigt af operativsystem, for det samme bliver læst. Den
|
||||
rå data kan dekodes som et filsystem hvor den rå data oversættes til
|
||||
filer og mapper. Både Mac, Windows og GNU/Linux kan læse filsystemet på
|
||||
cd'en, men på GNU/Linux læses ikke hele filsystemet. På GNU/Linux er det
|
||||
let at læse den rå data, så jeg lavede en undersøgelse. Jeg kiggede den
|
||||
rå data igennem for de filnavne GNU/Linux kunne dekode fra cd'en samt
|
||||
det indhold der var i filerne. Cd'en burde bruge et simpelt
|
||||
ISO9660-filsystem, så filnavnene og filindholdene burde bare være
|
||||
direkte læselige, hvilket de også var. Derefter forsøgte jeg samme
|
||||
søgemetode med nogle af de nye filer der var på den usb-stick jeg havde
|
||||
fået udleveret: Jeg fandt intet indhold. Alt det jeg ikke fandt må altså
|
||||
være krypteret på en eller anden Windows- og Mac-venlig måde. Der er
|
||||
ingen grund til at kryptere det.
|
||||
|
||||
Dette er de rodmapper og -filer (efter media/) som jeg har adgang til på
|
||||
den krypterede cd:
|
||||
|
||||
: error.html files/ index.html loading.html xit!.html
|
||||
|
||||
Dette er de mapper og filer jeg har adgang til hvis jeg kunne dekryptere
|
||||
cd'en (data fra usb-stick):
|
||||
|
||||
: data/ files/ flashplayer/ images/ index.html js/ styles/ xit!.html
|
||||
|
||||
Som eksempel på min filsystemssøgning kan vi tage filen 'index.html' som
|
||||
var i den ukrypterede del af cd'en, og filen 'data/uvmXml.xml' som jeg
|
||||
ikke kunne læse fra cd'en.
|
||||
|
||||
Filen 'index.html' eksisterer:
|
||||
|
||||
: $ grep -i index.htm engeks11cd.iso
|
||||
: Binary file engeks11cd.iso matches
|
||||
|
||||
Og indholdet eksisterer også ('<body
|
||||
onload="UVM.view.funcFitToScreen()">' er unikt nok til kun at forekomme
|
||||
i 'index.html'):
|
||||
|
||||
: $ grep '<body onload="UVM.view.funcFitToScreen()">' engeks11cd.iso
|
||||
: Binary file engeks11cd.iso matches
|
||||
|
||||
Vi ser at 'uvmXml.xml' faktisk også eksisterer:
|
||||
|
||||
: $ grep -i uvmXml.xml engeks11cd.iso
|
||||
: Binary file engeks11cd.iso matches
|
||||
|
||||
Men hvad med dens indhold? Fra usb-sticken ved jeg at 'uvmXml.xml' har
|
||||
mange '<CONTENT>'-tags. Så:
|
||||
|
||||
: $ grep -i '<CONTENT>' engeks11cd.iso
|
||||
: $ echo $?
|
||||
: 1
|
||||
|
||||
Indholdet i 'uvmXml.xml' er altså ikke tilgængeligt uden dekryptering.
|
||||
|
||||
Og så lige en anden teknisk ting: Jeg vil ikke blande mig så meget i
|
||||
jeres måde at lave webinterfacet på, men er JavaScript virkelig
|
||||
nødvendigt? Det føles som overkill at bruge jsQuery til at hente data
|
||||
fra en XML-fil og så servere det som HTML. I oplægget fra skriftlig
|
||||
engelsk 2010 var de forskellige ting pænt delt op i separate HTML-filer
|
||||
uden voldsomt brug af scripting. Der er sikkert nogle få elever der har
|
||||
slået JavaScript fra i deres browsere, så det er bedst at holde det
|
||||
simpelt.
|
||||
|
||||
|
||||
|
||||
Nå, bortset fra det var årets stilemne godt.
|
||||
|
||||
|
||||
Relevante links:
|
||||
|
||||
+ [[http://gnu.org/]]
|
||||
+ [[http://fsf.org/]]
|
||||
+ [[http://webmproject.org/]]
|
||||
+ [[http://xiph.org/]]
|
||||
+ [[http://theora.org/cortado/]]
|
||||
+ [[http://w3.org/]]
|
||||
+ [[http://w3.org/TR/html5/video.html]]
|
||||
|
||||
|
||||
V.h. Niels Serup 3. E, HTX Hillerød (snart student)[fn:done]
|
||||
|
||||
|
||||
[fn:done] Jeg blev student i juni.
|
||||
@@ -1,12 +0,0 @@
|
||||
#+title: The Trasbexian Flow Regulator
|
||||
#&summary
|
||||
A story
|
||||
#&
|
||||
#+license: wtfpl
|
||||
|
||||
* The Trasbexian Flow Regulator
|
||||
|
||||
"The Trasbexian Flow Regulator" is a short story by Niels. It is available under CC
|
||||
BY-SA 3.0+ as an A5-sized 12-paged pdf.
|
||||
|
||||
<@html <a href='tfr.pdf'>Download.<br /><img src='p1.png' alt='Front page' /></a>@>
|
||||
|
Before Width: | Height: | Size: 11 KiB |
@@ -1,134 +0,0 @@
|
||||
#+title: Two spaces
|
||||
#&summary
|
||||
Not one.
|
||||
#&
|
||||
#+license: wtfpl
|
||||
#+startup: showall
|
||||
#&toc
|
||||
|
||||
|
||||
* Two spaces
|
||||
|
||||
When I end a sentence and intend on writing a new, I type two spaces instead of
|
||||
one.
|
||||
|
||||
I do this only to separate sentence endings from period-terminated
|
||||
abbreviations. Consider this sentence:
|
||||
|
||||
: I eat couches, e.g. brown ones. They are nice.
|
||||
|
||||
If you didn't know that "e.g." is an abbreviation, you might think that there
|
||||
are three sentences: "I eat couches, e.g.", "brown ones.", and "They are nice."
|
||||
|
||||
Now consider this sentence:
|
||||
|
||||
: I eat couches, e.g. brown ones. They are nice.
|
||||
|
||||
By typing two spaces between the sentences, I have made clear that there are
|
||||
only two sentences, and that the period in "e.g." is not the end of a sentence.
|
||||
|
||||
The problem is that the period has two purposes: To end a sentence and to end
|
||||
some abbreviations. Always using two spaces to separate sentences solves this.
|
||||
|
||||
|
||||
* Other solutions
|
||||
|
||||
** Revolution
|
||||
|
||||
The best solution would be to use a separate character for abbreviation
|
||||
termination, or none at all, so that the period is exclusively used for ending
|
||||
sentences.
|
||||
|
||||
|
||||
** No change
|
||||
|
||||
One might think that another solution is to use just one space, the very thing
|
||||
that I'm arguing against. In the example above with one space between
|
||||
sentences, it's actually /not/ difficult to see that there are only two
|
||||
sentences: We know that a sentence must start with an uppercase letter, and
|
||||
"brown" after "e.g." does not, so it's not a new sentence.
|
||||
|
||||
However, uppercase letters *can* occur after abbreviations if they are part of
|
||||
given names. Consider this sentence:
|
||||
|
||||
: I eat couches, e.g. Priscilla's brown one. They are nice.
|
||||
|
||||
It's not clear that "Priscilla'" does not start a new sentence, because it's very
|
||||
similar to "They": Both words start with an uppercase letter and are placed
|
||||
after a period and a space. But "Priscilla's" is just another word in the first
|
||||
sentence!
|
||||
|
||||
This almost shows that the one-space methodology is insufficient, but not
|
||||
completely. One can argue that if we know all valid abbreviations, we can just
|
||||
check if a period is an end to an abbreviation or not, and determine that way
|
||||
whether it's a sentence.
|
||||
|
||||
But this is only true if the abbreviation can be used in only one way! Read
|
||||
this sentence:
|
||||
|
||||
: I used to eat couches bef. I found the cow.
|
||||
|
||||
It uses the abbreviation "bef." for "before"; see
|
||||
[[http://public.oed.com/how-to-use-the-oed/abbreviations/]].
|
||||
|
||||
The sentence can be read in two ways: Either you read it as one sentence -- "I
|
||||
used to eat couches before I found the cow" -- or you read it as two sentences
|
||||
-- "I used to eat couches before." and "I found the cow."
|
||||
|
||||
Both are valid (at least if you accept that a preposition can be the last word
|
||||
in a sentence).
|
||||
|
||||
I admit that that this example is a bit extreme. After all, most abbreviations
|
||||
can be used only in unambigious ways. Nevertheless, it still shows that just
|
||||
using a single space between sentences *is insufficient*!
|
||||
|
||||
Also, we have assumed that all abbreviations are known, which excludes temporary
|
||||
(and to some extent field-specific) abbreviations. This is not good! It's much
|
||||
easier to just use two spaces between your sentences!
|
||||
|
||||
|
||||
* Two spaces and fixed width output
|
||||
|
||||
Due to my background/foreground as a programmer, I have a tendency to limit
|
||||
myself to 80 characters per line, and write two newlines when I start a new
|
||||
paragraph (just look at the source of this page).
|
||||
|
||||
This is just a choice of representation which works well in many cases, but I
|
||||
won't write about that. The interesting thing is: How does this mix with using
|
||||
two spaces between sentences? This can actually be a problem; look at this
|
||||
sentence:
|
||||
|
||||
: Bla bla bla bla bef. bla bla.
|
||||
|
||||
This is one sentence, as "bef." does not end the sentence. If we assume that
|
||||
the line width is not 80 characters, but instead 16 characters, then the line
|
||||
should be wrapped like this:
|
||||
|
||||
#+BEGIN_SRC
|
||||
Bla bla bla bef.
|
||||
bla bla
|
||||
#+END_SRC
|
||||
|
||||
But now it's not clear if "bef." ends a sentence or not! If we want to turn the
|
||||
fixed-width representation back into a simple line representation, we don't know
|
||||
if we should insert one or two spaces after "bef.". How do we solve that?
|
||||
|
||||
The answer is that, when you line-wrap, you don't split word sequences separated
|
||||
by ". ", .i.e. you see an abbreviation and its following word as a single word.
|
||||
That way, you would end up with:
|
||||
|
||||
#+BEGIN_SRC
|
||||
Bla bla bla
|
||||
bef. bla bla
|
||||
#+END_SRC
|
||||
|
||||
which would not cause any problems.
|
||||
|
||||
|
||||
* General thoughts
|
||||
|
||||
Most natural languages have some amount of unambiguity, and part of it seems to
|
||||
make some things easier, i.e. allowing speakers to be loose when talking about
|
||||
stuff.
|
||||
|
||||
This other kind of ambiguity doesn't help anyone.
|
||||
|
Before Width: | Height: | Size: 39 KiB |
@@ -1,28 +0,0 @@
|
||||
#+title: Unnamed Good Story
|
||||
#&summary
|
||||
Wrote it because it was fun, stopped when it was not fun anymore.
|
||||
#&
|
||||
#+license: wtfpl
|
||||
|
||||
#&img;url=frontpage.png,center,medlink=unnamed-good-story.pdf,float=left,alt=Front page
|
||||
|
||||
* Unnamed Good Story
|
||||
|
||||
1. Good (it's in the title)
|
||||
2. 9 word-packed chapters full of words
|
||||
3. Good, simple language
|
||||
4. Above 0.5 on the witty scale (0 is not witty, 1 is completely witty)
|
||||
5. Short chapters
|
||||
6. Few characters to learn
|
||||
7. One strange character
|
||||
8. Simple plot
|
||||
9. Culturally exotic (written by a Danish person)
|
||||
10. I never finished it
|
||||
|
||||
I think the first chapter is the best chapter.
|
||||
|
||||
Comments can be sent to my email address, found [[/about/niels][here]].
|
||||
|
||||
#&clear
|
||||
Click on the picture to download the story in PDF.
|
||||
|
||||
|
Before Width: | Height: | Size: 396 KiB |
|
Before Width: | Height: | Size: 609 KiB |
|
Before Width: | Height: | Size: 359 KiB |
|
Before Width: | Height: | Size: 321 KiB |
|
Before Width: | Height: | Size: 460 KiB |
|
Before Width: | Height: | Size: 227 KiB |
|
Before Width: | Height: | Size: 437 KiB |
|
Before Width: | Height: | Size: 586 KiB |
|
Before Width: | Height: | Size: 426 KiB |
|
Before Width: | Height: | Size: 473 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
@@ -1,256 +0,0 @@
|
||||
#+title: Unhappy About Happy: A Reflection or Something Like That
|
||||
#&summary
|
||||
Rant about Haskell's parser "Happy".
|
||||
#&
|
||||
#+license: wtfpl
|
||||
#+startup: showall
|
||||
#&toc
|
||||
|
||||
#&img;url=UNHAPPY.PNG,float=right
|
||||
|
||||
* Unhappy About Happy: A Reflection or Something Like That
|
||||
|
||||
For the purposes of my quiet rage, this document will be written in all caps.
|
||||
I also will not use proper language. I won't even give suggestions on how to
|
||||
improve Happy; I'll just complain.
|
||||
|
||||
STARTING NOW
|
||||
|
||||
|
||||
** WHAT HAPPY ???
|
||||
|
||||
HAPPY IS PARSER GENERATOR. IT GENERATE HASKELL CODE. VISIT
|
||||
[[http://www.haskell.org/happy/][HTTP://WWW.HASKELL.ORG/HAPPY/]] FOR UGLY INFO.
|
||||
|
||||
|
||||
** HOW HAPPY GOOD
|
||||
|
||||
+ EFFICIENT I GUESS
|
||||
+ WORKS OK
|
||||
+ PRETTY LOGO
|
||||
|
||||
|
||||
** WHY I NOT LIKE HAPPY
|
||||
|
||||
*** JUZT TYPICAL
|
||||
|
||||
#+caption: ONE REASON. TRUST NOT BUSH WITH HAPPY
|
||||
#&img;url=MEME0.PNG,float=center
|
||||
|
||||
ONE ERROR IN PARSER.Y GIVE HUGE TYPE ERROR
|
||||
|
||||
*WHAT IS THIS!*
|
||||
|
||||
|
||||
#+BEGIN_SRC
|
||||
dist/build/l0c/l0c-tmp/Language/L0/Parser/Parser.hs:2452:42:
|
||||
Couldn't match type `Value' with `BasicValue -> Value'
|
||||
Expected type: HappyAbsSyn
|
||||
(Name, SrcLoc)
|
||||
[(Name,
|
||||
DeclTypeBase Name,
|
||||
[ParamBase Name],
|
||||
ExpBase NoInfo Name,
|
||||
SrcLoc)]
|
||||
(Name,
|
||||
DeclTypeBase Name,
|
||||
[ParamBase Name],
|
||||
ExpBase NoInfo Name,
|
||||
SrcLoc)
|
||||
Uniqueness
|
||||
([Maybe (DimSize Name)], ElemTypeBase NoInfo Name)
|
||||
(ElemTypeBase NoInfo Name)
|
||||
[TypeBase NoInfo Name]
|
||||
[TypeBase NoInfo Name]
|
||||
[ParamBase Name]
|
||||
(Maybe (CertificatesBase NoInfo Name), [ExpBase NoInfo Name])
|
||||
[ExpBase NoInfo Name]
|
||||
[ExpBase NoInfo Name]
|
||||
/* ... 200-300 MORE LINES ... */
|
||||
[TupIdentBase NoInfo Name]
|
||||
(TupIdentBase NoInfo Name)
|
||||
(LambdaBase NoInfo Name)
|
||||
(TupleLambdaBase NoInfo Name)
|
||||
(BasicValue -> Value)
|
||||
Int
|
||||
(BasicValue -> Value)
|
||||
(BasicValue -> Value)
|
||||
(BasicValue -> Value)
|
||||
(BasicValue -> Value)
|
||||
(BasicValue -> Value)
|
||||
Value
|
||||
(BasicValue -> Value)
|
||||
(BasicValue -> Value)
|
||||
[Value]
|
||||
[Value]
|
||||
In the second argument of `happySpecReduce_3', namely
|
||||
`happyReduction_191'
|
||||
In the expression: happySpecReduce_3 38# happyReduction_191
|
||||
In an equation for `happyReduce_191':
|
||||
happyReduce_191 = happySpecReduce_3 38# happyReduction_191
|
||||
#+END_SRC
|
||||
|
||||
*NOT NICE NOT NICE AT ALL*
|
||||
|
||||
|
||||
*** MONADA CAN I HAZ
|
||||
|
||||
MAYHAPS U NEED TO PARSE DIFFERENT THAN NORMAL KAY. HOW U THINK. YES:
|
||||
MENTALINCRMENTAL PARSING IT IS
|
||||
|
||||
#+caption: TWO REASON (I UNGOOD TO MEMES)
|
||||
#&img;url=MEME1.PNG,float=center
|
||||
|
||||
YOU GOT NEED TO PARSE IO GETLINE SOURCES YEAH
|
||||
|
||||
PARSE EXPRESSION "2 + 1 *4" OVER MULTI LINES LIKE THIS HERE
|
||||
|
||||
#+BEGIN_SRC
|
||||
WELCOM TO DA FUNKY MULTILINE EXPRESSION PARSER; ENTER UR EXPRESSION
|
||||
> 2 +
|
||||
1 *4
|
||||
TY GOT IT!! PARSED EXPRESSION IS "2 + 1 * 4" AND U NICE; RESULT IS 6 BTW
|
||||
>
|
||||
#+END_SRC
|
||||
|
||||
PARSER SHOULD KNOW "YEAH NOT DUHNE PARSIN YET" WHEN "2 +" READ, SHOULD TEHN
|
||||
READ NEW LINE AND PARSE MORE!
|
||||
|
||||
WE CAN PARSE FROM BEGINNING EVERY TIME SURE BUT INEFECICIENT!!!
|
||||
|
||||
#+caption: WE NOT WANT TIS SAYS PICARD 8-)
|
||||
#&img;url=MEME2.PNG,float=center
|
||||
|
||||
BUT HOW WE SHOULD / COULD DO THAT SMARTLY I IMPLORE TO LIKE ASK U
|
||||
|
||||
#+caption: CLEVER GILES HAS OUR SOLUTION!!!!!
|
||||
#&img;url=MEME3.PNG,float=center
|
||||
|
||||
YES WE USE CONTINUATION WHICH SMART. LOOK ATTOPARSEC USE CONTINUATION IN
|
||||
RETURN!
|
||||
[[http://hackage.haskell.org/package/attoparsec-0.11.1.0/docs/Data-Attoparsec-Text.html#t:IResult][HTTP://HACKAGE.HASKELL.ORG/PACKAGE/ATTOPARSEC-0.11.1.0/DOCS/DATA-ATTOPARSEC-TEXT.HTML#T:IRESULT]]
|
||||
|
||||
YEAH BUT NOT IN HAPPY............
|
||||
|
||||
SO WE MAKE IT MANUAL. WE SPECIFY OWN LEXER AND IMPROVE MONAD. WHEN END OF
|
||||
LINE IS REACH, WE TELL PARSER (FROM INSIDE DA PRASER) DAT DERE IS NO MORE EVER;
|
||||
IF THAT FAILS WE CATCH ERROR (EITHER-LIKE MONAD) AND READ NEW LINE FOR REALS
|
||||
|
||||
#+caption: AS MANY LINES AS LE POSSIBLÉ
|
||||
#&img;url=MEME4.PNG,float=center
|
||||
|
||||
CLEVER SOLUTION OF US! BUT IN PARSE EXPRESION EXAMPLE ABOV WE USE IO TO GETLINE
|
||||
|
||||
*WE NOT WANT IO IN ALL PARSING.... EVER EVER!!!!!!!!*
|
||||
|
||||
HOWTO ABSTRACT IO AWAY? WE WANT TYPE OF EXPORTED FUNCTIONS FROM PARSER TO NOT
|
||||
USE _IO_ /AT ALL/
|
||||
|
||||
#+caption: YAEH BABBY
|
||||
#&img;url=MEME5.PNG,float=center
|
||||
|
||||
SO WE USE WHATEVER MONAD TO GETLINE RIGHT?
|
||||
|
||||
#+BEGIN_SRC haskell
|
||||
class GetLiner m where -- KAY SO m IS MONAD RIGHT
|
||||
getSomeLine :: m String
|
||||
|
||||
instance GetLiner IO where
|
||||
getSomeLine = getLine
|
||||
#+END_SRC
|
||||
|
||||
WAIT I DONT GET IT
|
||||
|
||||
#+BEGIN_SRC haskell
|
||||
CLASS GETLINER M WHERE -- KAY SO M IS MONAD RIGHT
|
||||
GETSOMELINE :: M STRING
|
||||
|
||||
INSTANCE GETLINER IO WHERE
|
||||
GETSOMELINE = GETLINE
|
||||
#+END_SRC
|
||||
|
||||
MUCH BETTR. COZ TEHN WE CAN USE
|
||||
|
||||
#+caption: ... THEN WAT. Y U SO SLACK
|
||||
#&img;url=MEME6.PNG,float=center
|
||||
|
||||
BUT YIAH WE COULD USE TYPE CONSTRAINTS!
|
||||
|
||||
#+BEGIN_SRC haskell
|
||||
LEXER :: GETLINER M => M SOMETHNIG
|
||||
LEXER = MEHMEHMEH
|
||||
WOO <- GETSOMELINE
|
||||
MEH MEH
|
||||
#+END_SRC
|
||||
|
||||
SURE COULD WORK WE NEED JUST TELL HAPPY BOUT IT.
|
||||
|
||||
#+BEGIN_SRC
|
||||
%MONAD { GETLINER M => SOMETHINNG M }
|
||||
#+END_SRC
|
||||
|
||||
FAILS MISERBLY.................... :-( :( :(
|
||||
|
||||
WE ARE LEFT 4 PONDER HOW TO SOLVE! HOWTO ABSTRAKT OUT IO! HOW!!
|
||||
|
||||
#+caption: TRANCEND CONVENTIONAL COMPUTATIN U CAPITALIS PIG
|
||||
#&img;url=MEME7.PNG,float=center
|
||||
|
||||
SOOOO..... WE NEED KINDA CONTINUATIN COMPUTATON MONADY THINGY. I GOT FRIEND
|
||||
WHO COME WIT CODE, SAY IT GOOD CODE. I CHECK, HE RIGHT! IS HERE
|
||||
|
||||
#+BEGIN_SRC haskell
|
||||
DATA READLINEMONAD A = VALUE A
|
||||
| GETLINE (STRING -> READLINEMONAD A)
|
||||
|
||||
INSTANCE MONAD READLINEMONAD WHERE
|
||||
RETURN = VALUE
|
||||
VALUE X >>= F = F X
|
||||
GETLINE G >>= F = GETLINE $ \S -> G S >>= F
|
||||
#+END_SRC
|
||||
|
||||
HA CLEVER!!! NOW WE NEED NO TYPE CONSTRAINTS BECAUSE NOW COMPUTATION IS MONAD
|
||||
ITSELF! HOW YOU ASK.
|
||||
|
||||
READLINEMONAD HAS NO IO OR ANY ELSE BUILTIN; IT GETS LINE BY CREATE FUNCTION
|
||||
WHICH TAKES LINE TO CONTINUU EXECUTION. AGAIN AND AGAIN! LINE CAN COME FROM
|
||||
ANYTHIN.
|
||||
|
||||
EXAMPLE FOR USING RESULT!
|
||||
#+BEGIN_SRC haskell
|
||||
GETLINESFROMIO :: READLINEMONAD A -> IO A
|
||||
GETLINESFROMIO (VALUE X) = RETURN X
|
||||
GETLINESFROMIO (GETLINE F) = DO
|
||||
S <- GETLINE
|
||||
GETLINESFROMIO $ F S
|
||||
#+END_SRC
|
||||
|
||||
U SEE WAT GOIN ON DERE! IN OUR LEXER WE NAMELI USED
|
||||
#+BEGIN_SRC haskell
|
||||
GETLINE VALUE
|
||||
#+END_SRC
|
||||
|
||||
TO GET LINE (BECAUSE FITS WITH CLEVER MONAD!)
|
||||
|
||||
*NICE-O!*
|
||||
|
||||
|
||||
** CODE IN QUSTION
|
||||
|
||||
LOOKIE HER FOR FULL DETAILS (ALTHOU WITH NO FULL CAPS):
|
||||
[[https://raw.github.com/HIPERFIT/L0Language/master/src/Language/L0/Parser/Parser.y][HTTPS://RARRW.GITHUB.COM/HIPERFIT/L0LANGUAGE/MASTER/SRC/LANGUAGE/L0/PARSER/PARSER.Y]]
|
||||
|
||||
|
||||
** CONCLUSION
|
||||
|
||||
#+caption: TRU STORY
|
||||
#&img;url=MEME8.PNG,float=center
|
||||
|
||||
#+caption: NOT ME
|
||||
#&img;url=MEME9.PNG,float=center
|
||||
|
||||
THIS IS ENTRELY OBJECTIVE.
|
||||
|
||||
THIS IS ENTIREY OBJECTIVE.
|
||||
|
||||
THIS IS ENTIRLY OBJECTIVE.
|
||||