Put the misc. stuff in the top dir.

This commit is contained in:
2016-08-30 21:46:31 +02:00
parent f31b09a82f
commit 86b86ccdc0
54 changed files with 306 additions and 23 deletions

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -1,9 +0,0 @@
#+title: Hacking
#&summary
Hackety hack.
#&
#+startup: showall
* Hacking
I use the term "hacking" to mean "playing with".

View File

@@ -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!]]

View File

@@ -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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

View File

@@ -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.

Binary file not shown.

View File

@@ -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

Binary file not shown.

View File

@@ -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.

View File

@@ -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 |

View File

@@ -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]].

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

View File

@@ -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>

View File

@@ -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>@>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 KiB

Binary file not shown.

View File

@@ -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

View File

@@ -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]].

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

View File

@@ -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.

View File

@@ -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>@>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

View File

@@ -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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

View File

@@ -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.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 609 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 359 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 460 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 437 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 473 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -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.