Jul 26: pdfnup --trim
Parameterreihenfolge ist: "left bottom right top", Eselsbrücke: css rückwärts.
Jun 23: Verweissalat 1
BugSpy
checkmycode
Panopticlick (browser tracking)
TinEye Reverse Image Search
wtfjs (JS)
A Twisty Maze of Linux Clocks, All Slightly Different
C Language Quirks
Command-Line Printing and Options (cups)
Data Compression Explained
How Not To Sort By Average Rating
List of Printers Which Do or Do Not Display Tracking Dots
List of software development philosophies
Online Emulation of Soviet Ternary Computer Setun
Tail Call Improvements in .NET Framework 4
Ten divisions to Easter
Zip Files All The Way Down
Charity
dompdf
GeSHI
phash (perceptual hash library)
pixlr (online graphics editor)
push (dataflow shell)
re2 (regular expressions)
SQL Buddy
stringencoders (string transformations)
The Disciplined Disciple Compiler (strict evaluated Haskell)
The Maxine Virtual Machine
The Transterpreter Project (vm)
tinypy
tmux
checkmycode
Panopticlick (browser tracking)
TinEye Reverse Image Search
wtfjs (JS)
A Twisty Maze of Linux Clocks, All Slightly Different
C Language Quirks
Command-Line Printing and Options (cups)
Data Compression Explained
How Not To Sort By Average Rating
List of Printers Which Do or Do Not Display Tracking Dots
List of software development philosophies
Online Emulation of Soviet Ternary Computer Setun
Tail Call Improvements in .NET Framework 4
Ten divisions to Easter
Zip Files All The Way Down
Charity
dompdf
GeSHI
phash (perceptual hash library)
pixlr (online graphics editor)
push (dataflow shell)
re2 (regular expressions)
SQL Buddy
stringencoders (string transformations)
The Disciplined Disciple Compiler (strict evaluated Haskell)
The Maxine Virtual Machine
The Transterpreter Project (vm)
tinypy
tmux
Geschrieben von Frank
in Informatik
Jun 8: c++ productivity
Wieder ein schöner Beitrag von Linus Trovalds über C++:
Punktlandung.
So there are particular reasons why I think C is "as simple
as possible, but no simpler" for the particular case of an
OS kernel, or system programming in particular. That's why
I'm absolutely not saying that you should use C for all
projects.
But C++? I really don't think the "good features" of it
are very good at all. If you leave C behind, do it properly
and get some real features that matter. GC, some
concurrency support, dynamic code generation, whatever.
Punktlandung.
Mai 16: von dwm und mrxvt zu Xmonad und urxvt
Mit der Entwicklung von dwm war ich schon eine Weile unzufrieden, Xmonad hingegen hat sich seit meinem ersten Versuch vor drei Jahren inzwischen zu einem richtigen Metafenstermanager entwickelt. Nahezu jede Funktion ist anpassbar und bereits in mehreren Varianten verfügbar, ganz ohne C schreiben oder veraltete Patches anpassen zu müssen. Sehr, sehr nett.
Die erste .xmonad/xmonad.hs - weitestgehend zusammenkopiert aus der Doku:
import XMonad
import XMonad.Actions.DwmPromote
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageDocks
import XMonad.Layout.Tabbed
import XMonad.Util.Run(spawnPipe)
import Data.Monoid
import System.Exit
import System.IO.UTF8
import qualified XMonad.StackSet as W
import qualified Data.Map as M
myTerminal = "urxvtc"
myFocusFollowsMouse :: Bool
myFocusFollowsMouse = True
myBorderWidth = 1
myModMask = mod4Mask
myNumlockMask = mod2Mask
myWorkspaces = ["1","2","3","4","5:www","6:min"]
myNormalBorderColor = "#dddddd"
myFocusedBorderColor = "#ff0000"
myKeys conf@(XConfig {XMonad.modMask = modm}) = M.fromList $
[ ((modm .|. shiftMask, xK_Return), spawn $ XMonad.terminal conf)
, ((modm, xK_p ), spawn "exe=`dmenu_path | dmenu` && eval \\"exec $exe\\"")
, ((modm .|. shiftMask, xK_c ), kill)
, ((modm, xK_space ), sendMessage NextLayout)
, ((modm .|. shiftMask, xK_space ), setLayout $ XMonad.layoutHook conf)
, ((modm, xK_n ), refresh)
, ((modm, xK_Tab ), windows W.focusDown)
, ((modm, xK_j ), windows W.focusDown)
, ((modm, xK_k ), windows W.focusUp )
, ((modm, xK_m ), windows W.focusMaster )
, ((modm, xK_Return), dwmpromote)
, ((modm .|. shiftMask, xK_j ), windows W.swapDown )
, ((modm .|. shiftMask, xK_k ), windows W.swapUp )
, ((modm, xK_h ), sendMessage Shrink)
, ((modm, xK_l ), sendMessage Expand)
, ((modm, xK_t ), withFocused $ windows . W.sink)
, ((modm , xK_comma ), sendMessage (IncMasterN 1))
, ((modm , xK_period), sendMessage (IncMasterN (-1)))
, ((modm , xK_b ), sendMessage ToggleStruts)
, ((modm .|. shiftMask, xK_q ), io (exitWith ExitSuccess))
, ((modm , xK_q ), spawn "xmonad --recompile; xmonad --restart")
]
++
[((m .|. modm, k), windows $ f i)
| (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9]
, (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]
++
[ ((modm, xK_o), spawn "opera -nomail -nolirc")
, ((modm, xK_e), spawn "claws-mail")
, ((modm, xK_f), spawn "firefox")
, ((modm, xK_g), spawn "gqview")
, ((modm .|. shiftMask, xK_g), spawn "gvim")
, ((modm, xK_s), spawn "urxvt -pe tabbed,matcher")
, ((modm, xK_less), windows $ W.greedyView "5:www")
]
myMouseBindings (XConfig {XMonad.modMask = modm}) = M.fromList $
[ ((modm, button1), (\w -> focus w >> mouseMoveWindow w
>> windows W.shiftMaster))
, ((modm, button2), (\w -> focus w >> windows W.shiftMaster))
, ((modm, button3), (\w -> focus w >> mouseResizeWindow w
>> windows W.shiftMaster))
]
myLayout = avoidStruts(tiled ||| Mirror tiled ||| simpleTabbedAlways ||| Full)
where
tiled = Tall nmaster delta ratio
nmaster = 1
ratio = 7/10
delta = 5/100
myManageHook = composeAll
[ className =? "Gimp" --> doFloat
, className =? "MPlayer" --> doFloat
, className =? "Opera" --> doShift "5:www"
,(className =? "Firefox" <&&> resource =? "Dialog") --> doFloat ]
myEventHook = mempty
myLogHook h = dynamicLogWithPP $ myPP h
myPP h = defaultPP
{ ppCurrent = wrap "^bg(#e5f9ff)^fg(#105468)" "^bg()^fg()"
, ppVisible = wrap "^fg(#a00000)" "^fg()"
, ppHidden = wrap "^fg(#ffffff)" "^fg()"
, ppHiddenNoWindows = wrap "^fg(#7eacb9)" "^fg()"
, ppSep = " | "
, ppWsSep = " "
, ppTitle = shorten 80
, ppOrder = workspaceTag
, ppOutput = System.IO.UTF8.hPutStrLn h
}
where workspaceTag (x:xs) = ("[ " ++ x ++ " ]") : xs
myStartupHook = return ()
main = do dzenh <- spawnPipe "dzen2 -p -w 1280 -ta l"
xmonad $ defaults dzenh
defaults dzenh = defaultConfig {
terminal = myTerminal,
focusFollowsMouse = myFocusFollowsMouse,
borderWidth = myBorderWidth,
modMask = myModMask,
numlockMask = myNumlockMask,
workspaces = myWorkspaces,
normalBorderColor = myNormalBorderColor,
focusedBorderColor = myFocusedBorderColor,
keys = myKeys,
mouseBindings = myMouseBindings,
layoutHook = myLayout,
manageHook = myManageHook,
handleEventHook = myEventHook,
logHook = myLogHook dzenh,
startupHook = myStartupHook
}
Die .xinitrc:
xsetroot -cursor_name left_ptr
urxvtd -f -o -q
exec xmonad
Der Ressourcenverbrauch ist höher, aber wenn ich dadurch schneller arbeiten kann, ist es mir egal.
PR NI VIRT RES SHR S %CPU %MEM TIME+
40 0 6916 3628 2496 S 0.0 0.7 0:00.05 xmonad
40 0 3020 1144 940 S 0.0 0.2 0:00.01 dzen2
40 0 3132 932 808 S 0.0 0.2 0:00.11 dwm
Gleiches gilt für mrxvt. Ein paar Bugs nervten auf Dauer (zB. Zeichenverlust beim Ändern der Fenstergröße) und die Dämonvariante urxvtd wird dem Tiling-Konzept meiner Meinung nach besser gerecht.
Die erste .xmonad/xmonad.hs - weitestgehend zusammenkopiert aus der Doku:
import XMonad
import XMonad.Actions.DwmPromote
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageDocks
import XMonad.Layout.Tabbed
import XMonad.Util.Run(spawnPipe)
import Data.Monoid
import System.Exit
import System.IO.UTF8
import qualified XMonad.StackSet as W
import qualified Data.Map as M
myTerminal = "urxvtc"
myFocusFollowsMouse :: Bool
myFocusFollowsMouse = True
myBorderWidth = 1
myModMask = mod4Mask
myNumlockMask = mod2Mask
myWorkspaces = ["1","2","3","4","5:www","6:min"]
myNormalBorderColor = "#dddddd"
myFocusedBorderColor = "#ff0000"
myKeys conf@(XConfig {XMonad.modMask = modm}) = M.fromList $
[ ((modm .|. shiftMask, xK_Return), spawn $ XMonad.terminal conf)
, ((modm, xK_p ), spawn "exe=`dmenu_path | dmenu` && eval \\"exec $exe\\"")
, ((modm .|. shiftMask, xK_c ), kill)
, ((modm, xK_space ), sendMessage NextLayout)
, ((modm .|. shiftMask, xK_space ), setLayout $ XMonad.layoutHook conf)
, ((modm, xK_n ), refresh)
, ((modm, xK_Tab ), windows W.focusDown)
, ((modm, xK_j ), windows W.focusDown)
, ((modm, xK_k ), windows W.focusUp )
, ((modm, xK_m ), windows W.focusMaster )
, ((modm, xK_Return), dwmpromote)
, ((modm .|. shiftMask, xK_j ), windows W.swapDown )
, ((modm .|. shiftMask, xK_k ), windows W.swapUp )
, ((modm, xK_h ), sendMessage Shrink)
, ((modm, xK_l ), sendMessage Expand)
, ((modm, xK_t ), withFocused $ windows . W.sink)
, ((modm , xK_comma ), sendMessage (IncMasterN 1))
, ((modm , xK_period), sendMessage (IncMasterN (-1)))
, ((modm , xK_b ), sendMessage ToggleStruts)
, ((modm .|. shiftMask, xK_q ), io (exitWith ExitSuccess))
, ((modm , xK_q ), spawn "xmonad --recompile; xmonad --restart")
]
++
[((m .|. modm, k), windows $ f i)
| (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9]
, (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]
++
[ ((modm, xK_o), spawn "opera -nomail -nolirc")
, ((modm, xK_e), spawn "claws-mail")
, ((modm, xK_f), spawn "firefox")
, ((modm, xK_g), spawn "gqview")
, ((modm .|. shiftMask, xK_g), spawn "gvim")
, ((modm, xK_s), spawn "urxvt -pe tabbed,matcher")
, ((modm, xK_less), windows $ W.greedyView "5:www")
]
myMouseBindings (XConfig {XMonad.modMask = modm}) = M.fromList $
[ ((modm, button1), (\w -> focus w >> mouseMoveWindow w
>> windows W.shiftMaster))
, ((modm, button2), (\w -> focus w >> windows W.shiftMaster))
, ((modm, button3), (\w -> focus w >> mouseResizeWindow w
>> windows W.shiftMaster))
]
myLayout = avoidStruts(tiled ||| Mirror tiled ||| simpleTabbedAlways ||| Full)
where
tiled = Tall nmaster delta ratio
nmaster = 1
ratio = 7/10
delta = 5/100
myManageHook = composeAll
[ className =? "Gimp" --> doFloat
, className =? "MPlayer" --> doFloat
, className =? "Opera" --> doShift "5:www"
,(className =? "Firefox" <&&> resource =? "Dialog") --> doFloat ]
myEventHook = mempty
myLogHook h = dynamicLogWithPP $ myPP h
myPP h = defaultPP
{ ppCurrent = wrap "^bg(#e5f9ff)^fg(#105468)" "^bg()^fg()"
, ppVisible = wrap "^fg(#a00000)" "^fg()"
, ppHidden = wrap "^fg(#ffffff)" "^fg()"
, ppHiddenNoWindows = wrap "^fg(#7eacb9)" "^fg()"
, ppSep = " | "
, ppWsSep = " "
, ppTitle = shorten 80
, ppOrder = workspaceTag
, ppOutput = System.IO.UTF8.hPutStrLn h
}
where workspaceTag (x:xs) = ("[ " ++ x ++ " ]") : xs
myStartupHook = return ()
main = do dzenh <- spawnPipe "dzen2 -p -w 1280 -ta l"
xmonad $ defaults dzenh
defaults dzenh = defaultConfig {
terminal = myTerminal,
focusFollowsMouse = myFocusFollowsMouse,
borderWidth = myBorderWidth,
modMask = myModMask,
numlockMask = myNumlockMask,
workspaces = myWorkspaces,
normalBorderColor = myNormalBorderColor,
focusedBorderColor = myFocusedBorderColor,
keys = myKeys,
mouseBindings = myMouseBindings,
layoutHook = myLayout,
manageHook = myManageHook,
handleEventHook = myEventHook,
logHook = myLogHook dzenh,
startupHook = myStartupHook
}
Die .xinitrc:
xsetroot -cursor_name left_ptr
urxvtd -f -o -q
exec xmonad
Der Ressourcenverbrauch ist höher, aber wenn ich dadurch schneller arbeiten kann, ist es mir egal.
PR NI VIRT RES SHR S %CPU %MEM TIME+
40 0 6916 3628 2496 S 0.0 0.7 0:00.05 xmonad
40 0 3020 1144 940 S 0.0 0.2 0:00.01 dzen2
40 0 3132 932 808 S 0.0 0.2 0:00.11 dwm
Gleiches gilt für mrxvt. Ein paar Bugs nervten auf Dauer (zB. Zeichenverlust beim Ändern der Fenstergröße) und die Dämonvariante urxvtd wird dem Tiling-Konzept meiner Meinung nach besser gerecht.
Mai 5: world update
Immer wieder schön, wie Software nerven kann. Bei emerge gibt es (noch) keine ignore-Option und so konnte Opera 10.10 nicht gegen das vorhandene Qt3 gebaut bleiben, nein es musste unbedingt Qt4 sein. Da ich diesen Bloat nicht auf dem Rechner haben will, blieb nur¹ das Demaskieren des instabilen Opera 10.53-pre6330 mit wunderschöner defekter Menüleiste, die man erst einschalten muss, nachdem man vorher den überflüssigen Quatsch (Unite etc.) abgestellt hat:

Was gab es sonst noch? mrxvt malt per default grüne Cursor (wtf?!), natürlich musste xorg-driver nochmal übersetzt werden um die Eingabegeräte nutzen zu können und ghc 6.12.2 wollte gar nicht erst kompilieren. Wenigstens ist Qt jetzt ganz vom Rechner verschwunden.
Aktualisierung:
Im ghc-Ebuild gehen sie von /usr/bin/gcc aus, beim Einsatz von ccache kann das nicht klappen:
# Relocate from /usr to ${WORKDIR}/usr
sed -i -e "s|${WORKDIR}$(type -P gcc)|$(type -P gcc)|g" \
¹ oder diverse Overlays

Was gab es sonst noch? mrxvt malt per default grüne Cursor (wtf?!), natürlich musste xorg-driver nochmal übersetzt werden um die Eingabegeräte nutzen zu können und ghc 6.12.2 wollte gar nicht erst kompilieren. Wenigstens ist Qt jetzt ganz vom Rechner verschwunden.
Aktualisierung:
Im ghc-Ebuild gehen sie von /usr/bin/gcc aus, beim Einsatz von ccache kann das nicht klappen:
# Relocate from /usr to ${WORKDIR}/usr
sed -i -e "s|${WORKDIR}$(type -P gcc)|$(type -P gcc)|g" \
¹ oder diverse Overlays
Apr 18: EU-Fahndungssystem vor dem Aus
EU-Fahndungssystem vor dem Aus
Übliches Schema:
Wer ist schuld?
Die Entwicklung des Fahndungssystems SIS II erweist sich als teures Debakel zur Verbrecherjagd. Die Bundesregierung will die Planungen jetzt beenden und setzt auf das bestehende System.
Übliches Schema:
Die Aufgabe von SIS II wäre allerdings ein teurer Fehlschlag. Ursprünglich waren laut Bundesregierung für SIS II 14,6 Millionen Euro vorgesehen. Inzwischen wurden aus dem EU-Haushalt aber bereits 76 Millionen Euro ausgegeben - ohne brauchbare Gegenleistung.
Wer ist schuld?
Angesprochen ist damit ein Konsortium um den Server-Hersteller Hewlett-Packard und die Software-Consultants von Steria Mummert.
Feb 13: Terrorisieren - verunglimpfen - mobben
Ich weiß schon, wieso ich vor vielen Jahren aufgehört habe, die c't zu lesen: Völlig anonym: Terrorisieren - verunglimpfen - mobben
Skandal! Bürger können telefonieren, ohne dass der Staat es weiß. Sind natürlich alles Terroristen, Stalker, Kinderpornographiekonsumenten usw.. Und am Ende noch scheinheilig über den "gläsernen Bürger" aufregen, weil man selbst zu doof war, seine Daten nicht wegzugeben und diese Regierung abzuwählen.
*würg
Unter falschem Namen lassen sich SIM-Karten von Mediamarkt, Saturn, Aldi, Netto Marken-Discount, Penny, Lidl und REWE per Internet oder telefonisch freischalten. Die Discounter leisten damit Straftaten wie dem Identitätsdiebstahl Vorschub.
Skandal! Bürger können telefonieren, ohne dass der Staat es weiß. Sind natürlich alles Terroristen, Stalker, Kinderpornographiekonsumenten usw.. Und am Ende noch scheinheilig über den "gläsernen Bürger" aufregen, weil man selbst zu doof war, seine Daten nicht wegzugeben und diese Regierung abzuwählen.
Falls das Verhalten der Prepaid-Anbieter folgenlos bleibt, ist das Wasser auf die Mühlen der Kritiker an der gängigen Speicherpraxis: Wenn ein derartiges Loch im Deich klafft, ist das Aufschichten von zusätzlichen Sandsäcken andernorts sinnlos. Und selbst wenn dieses Schlupfloch geschlossen wird, bleibt für Kriminelle, Terroristen und gesetzestreue Bürger, die Wert auf anonyme Kommunikation legen, immer noch der Kartenhandel über die Trödelmärkte, der Einsatz ausländischer Karten, der Besuch im Internetcafé, die Nutzung eines ungesicherten WLAN, ein Hotspot mit anonymer Guthabenkarte oder die gute alte Telefonzelle.
*würg
Jan 30: log escape sequence injection
log escape sequence injection
Manchmal verliert man wirklich das Vertrauen. Haben die die letzten 25 Jahre geschlafen? Ein-/Ausgabevalidierung anyone?
Nginx, Varnish, Cherokee, thttpd, mini-httpd, WEBrick, Orion, AOLserver, Yaws and Boa
Manchmal verliert man wirklich das Vertrauen. Haben die die letzten 25 Jahre geschlafen? Ein-/Ausgabevalidierung anyone?
Geschrieben von Frank
in Informatik
Jan 28: Googles "Lokales Branchenregister"
"Geben Sie unten Ihre Geschäftsinformationen ein." - würde ich ja gern, aber unter Firefox fehlt das Feld "Firma/Organisation" und es erscheint beim Senden eine Fehlerinformation und unter Opera ist der "Nächste"-Schalter kaputt. Wie kann man ein simples Formular derartig verkacken und mit JavaScript überladen?
Aktualisierung 29.01.2010: Der IE zählt die verbleibenden Zeichen falsch. Testen die nur noch mit Chrom(e|ium)?
Aktualisierung 29.01.2010: Der IE zählt die verbleibenden Zeichen falsch. Testen die nur noch mit Chrom(e|ium)?
Jan 13: Firefox suckt
Natürlich will man bei cloneNode() die Inhalte von textarea und select verlieren...
Test
Bug - offen seit 07.01.2004, alles Gute zum 6. Geburtstag nachträglich
Opera macht's richtig.
Test
Bug - offen seit 07.01.2004, alles Gute zum 6. Geburtstag nachträglich
Opera macht's richtig.
Geschrieben von Frank
in Informatik
Jan 1: Verweissalat 0
A regular expression to check for prime numbers
Aktion Uberwach
Brewer's CAP Theorem
Conway's Game of Life in one line of APL
IMDB DB
iPhone-Fans leiden unter dem Stockholm-Syndrom
JSNES: A Javascript NES emulator
Man or Boy Test
NOSQL Patterns
Quality-oriented teaching of programming
Sorting Algorithm Shootout
Spatial indexing with Quadtrees and Hilbert Curves
XOR Swap Algorithm
Aktion Uberwach
Brewer's CAP Theorem
Conway's Game of Life in one line of APL
IMDB DB
iPhone-Fans leiden unter dem Stockholm-Syndrom
JSNES: A Javascript NES emulator
Man or Boy Test
NOSQL Patterns
Quality-oriented teaching of programming
Sorting Algorithm Shootout
Spatial indexing with Quadtrees and Hilbert Curves
XOR Swap Algorithm
Geschrieben von Frank
in Informatik
Jan 1: C++ and the compile time faculty
I hate C++ fanboys. "Look C++ is the most p0werful and shiny language ev4r. You can't do that with any other language." followed by a copy of the faculty example from FQA or Wikipedia:
C++ dissolves the template to a simple multiplication (if -ftemplate-depth >= 4) and *woohoo replaces the multiplication with the result at compile time. There are many languages (and language features) out there with this capability, p.ex. Lisp Macros, Scheme, MetaOcaml or Template Haskell:
Fac.hs:
Main.hs:
120 at compile time:
#include <iostream>
using namespace std;
template<int n> struct fac {
static const int value = n*fac<n-1>::value;
};
template<> struct fac<1> {
static const int value = 1;
};
int main() {
cout << fac<5>::value << endl;
return 0;
}
using namespace std;
template<int n> struct fac {
static const int value = n*fac<n-1>::value;
};
template<> struct fac<1> {
static const int value = 1;
};
int main() {
cout << fac<5>::value << endl;
return 0;
}
C++ dissolves the template to a simple multiplication (if -ftemplate-depth >= 4) and *woohoo replaces the multiplication with the result at compile time. There are many languages (and language features) out there with this capability, p.ex. Lisp Macros, Scheme, MetaOcaml or Template Haskell:
Fac.hs:
Main.hs:
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Fac
import Language.Haskell.TH.Syntax
main = print $(lift $ fac (5 :: Int))
module Main where
import Fac
import Language.Haskell.TH.Syntax
main = print $(lift $ fac (5 :: Int))
120 at compile time:
>ghc -ddump-simpl Main.hs | grep print | grep 120
Main.main = print_rSB (GHC.Integer.smallInteger 120)
Main.main = print_rSB (GHC.Integer.smallInteger 120)
Okt 22: Bringing back the J to Bifid Cipher
As a programming language enthusiast I often examine new (to me) languages, paradigms and concepts. Recently I played with J - sth. like APL with keyboard friendly syntax. If you are familiar with point-free functional programming, J isn't that complicated. More tedious is the used vocabulary (verbs, nouns, frets, agenda, gerunds...) for trivial things and the fact, that you can't use search engines - neither for "J" (-> "site:jsoftware.com"), nor for a function symbol (combination).
Mind bending are the many one-liners and examples in the documentation. And believe me, there isn't much more satisfaction as in unraveling the first lines of J code. ;)
As practical example on "hello world" level I used the Bifid Cipher:
Keep in mind, this is of course not the shortest or fastest or nicest implementation. It's just my first J program.
A short explanation for the curious
Read from right to left, @ is function composition and & binds a parameter.
pre - prepare our string
1. take a list of characters (the string), convert every character to uppercase (toupper) and look up (&i.) the characters in the ascii table (a.)
2. subtract 65 (ascii value of 'A') from every list item (-&65) (a 0..4 indexed cipher table to save some inc- (>:) and decrements (<:))
3. and decrement every item greater than 9 (]->&9) for the missing 'J'(!)
The last part needs some explanation. (]->&9) is a so called "monadic fork". We have three functions f (] "identity"), h (- "minus") and g (>&9 "greater than 9") and the constellation as monadic fork (f h g) x executes as h(f(x),g(x)). The comparison gives a list of 0s and 1s, "NB." is line comment:
enc - encode
1. Now you are familiar with forks, you can interpret (<.@%&5,5&|) also, didn't you? On the left side we divide every element by 5 (%&5) and round (<. "floor") to the next smallest integer. On the other side we compute the remainder of the division with 5 (| "mod") and append (,) that list to our left result.
2. with ((%&2@#,2:)$[) we reshape ($) our list to nx2, n is the length (#) of the list divided by 2 (%&2), (2:) is the constant function, giving back 2
3. and transpose (|:) it for our final conversion in pst
dec - decode
Decode is similar to encode.
1. div (<.@%&5) and mod (%&|) our list but merge (,@,.) the result
2. and again reshape the result to 2xn with n as half list length
pst - result to string
1. we have to rebuild our string, so we take the first row ([/) and multiply with 5 (5&*) and add (+) the result to our second (]/) row, to which we added 66 (66&+)
2. we have to decrement the values below 75 ('K') (]-<&75)
3. and lookup our values in the ascii table ({&a.)
Now we can compose and use our encode and decode functions:
Another example
Not enough? I see you are as fascinated as I am. The next example ist from j602/system/main/convert.ijs
3 : '... y' defines a verb, imagine it as a function with one argument y. (()`()@.()) is:
Pure beauty! Here (2&=@(3!:0)) acts as a case or if expression. It returns a value which becomes the index of the left "list of functions" (take it with salt). 3!:0 returns the "type" (more salt!) of a parameter. If it is a character it returns 2, the following comparison (2&=) returns 1 and (a.&i) evaluates to the index of this character in the ascii table. Otherwise we assume it is a number and return the corresponding character.
Mind bending are the many one-liners and examples in the documentation. And believe me, there isn't much more satisfaction as in unraveling the first lines of J code. ;)
As practical example on "hello world" level I used the Bifid Cipher:
pre=:(]->&9)@-&65@(a.&i.@toupper)
enc=:|:@((%&2@#,2:)$[)@(<.@%&5,5&|)
dec=:((2:,%&2@#)$[)@(<.@%&5,@,.5&|)
pst=:{&a.@(]-<&75)@(5&*@[/+66&+@]/)
encode=:pst@enc@pre
decode=:pst@dec@pre
enc=:|:@((%&2@#,2:)$[)@(<.@%&5,5&|)
dec=:((2:,%&2@#)$[)@(<.@%&5,@,.5&|)
pst=:{&a.@(]-<&75)@(5&*@[/+66&+@]/)
encode=:pst@enc@pre
decode=:pst@dec@pre
Keep in mind, this is of course not the shortest or fastest or nicest implementation. It's just my first J program.
A short explanation for the curious
Read from right to left, @ is function composition and & binds a parameter.
pre - prepare our string
1. take a list of characters (the string), convert every character to uppercase (toupper) and look up (&i.) the characters in the ascii table (a.)
a.&i.@toupper 'hello'
72 69 76 76 79
72 69 76 76 79
2. subtract 65 (ascii value of 'A') from every list item (-&65) (a 0..4 indexed cipher table to save some inc- (>:) and decrements (<:))
-&65@(a.&i.@toupper) 'hello'
7 4 11 11 14
7 4 11 11 14
3. and decrement every item greater than 9 (]->&9) for the missing 'J'(!)
(]->&9)@-&65@(a.&i.@toupper) 'hello'
7 4 10 10 13
7 4 10 10 13
The last part needs some explanation. (]->&9) is a so called "monadic fork". We have three functions f (] "identity"), h (- "minus") and g (>&9 "greater than 9") and the constellation as monadic fork (f h g) x executes as h(f(x),g(x)). The comparison gives a list of 0s and 1s, "NB." is line comment:
NB. the identity (f):
] 7 4 11 11 14
7 4 11 11 14
NB. greater than 9 (g):
(>&9) 7 4 11 11 14
0 0 1 1 1
NB. together with minus h(f(x),g(x)):
(]->&9) 7 4 11 11 14
7 4 10 10 13
] 7 4 11 11 14
7 4 11 11 14
NB. greater than 9 (g):
(>&9) 7 4 11 11 14
0 0 1 1 1
NB. together with minus h(f(x),g(x)):
(]->&9) 7 4 11 11 14
7 4 10 10 13
enc - encode
1. Now you are familiar with forks, you can interpret (<.@%&5,5&|) also, didn't you? On the left side we divide every element by 5 (%&5) and round (<. "floor") to the next smallest integer. On the other side we compute the remainder of the division with 5 (| "mod") and append (,) that list to our left result.
(<.@%&5,5&|) 7 4 10 10 13
1 0 2 2 2 2 4 0 0 3
1 0 2 2 2 2 4 0 0 3
2. with ((%&2@#,2:)$[) we reshape ($) our list to nx2, n is the length (#) of the list divided by 2 (%&2), (2:) is the constant function, giving back 2
((%&2@#,2:)$]) 1 0 2 2 2 2 4 0 0 3
1 0
2 2
2 2
4 0
0 3
1 0
2 2
2 2
4 0
0 3
3. and transpose (|:) it for our final conversion in pst
|:((%&2@#,2:)$]) 1 0 2 2 2 2 4 0 0 3
1 2 2 4 0
0 2 2 0 3
1 2 2 4 0
0 2 2 0 3
dec - decode
Decode is similar to encode.
1. div (<.@%&5) and mod (%&|) our list but merge (,@,.) the result
NB. append from enc
(<.@%&5,5&|) 5 12 12 20 3
1 2 2 4 0 0 2 2 0 3
NB. merge from dec
(<.@%&5,@,.5&|) 5 12 12 20 3
1 0 2 2 2 2 4 0 0 3
(<.@%&5,5&|) 5 12 12 20 3
1 2 2 4 0 0 2 2 0 3
NB. merge from dec
(<.@%&5,@,.5&|) 5 12 12 20 3
1 0 2 2 2 2 4 0 0 3
2. and again reshape the result to 2xn with n as half list length
((2:,%&2@#)$[) 1 0 2 2 2 2 4 0 0 3
1 0 2 2 2
2 4 0 0 3
1 0 2 2 2
2 4 0 0 3
pst - result to string
1. we have to rebuild our string, so we take the first row ([/) and multiply with 5 (5&*) and add (+) the result to our second (]/) row, to which we added 66 (66&+)
NB. our table
t=:((2:,%&2@#)$[)@(<.@%&5,@,.5&|) 5 12 12 20 3
t
1 0 2 2 2
2 4 0 0 3
NB. first row
[/ t
1 0 2 2 2
NB. second row
]/ t
2 4 0 0 3
NB. multiply and add twice
(5&*@[/ + 66&+@]/) t
73 70 76 76 79
t=:((2:,%&2@#)$[)@(<.@%&5,@,.5&|) 5 12 12 20 3
t
1 0 2 2 2
2 4 0 0 3
NB. first row
[/ t
1 0 2 2 2
NB. second row
]/ t
2 4 0 0 3
NB. multiply and add twice
(5&*@[/ + 66&+@]/) t
73 70 76 76 79
2. we have to decrement the values below 75 ('K') (]-<&75)
(]-<&75)(5&*@[/ + 66&+@]/) t
72 69 76 76 79
72 69 76 76 79
3. and lookup our values in the ascii table ({&a.)
NB. decoding result
({&a.) 72 69 76 76 79
HELLO
NB. encoding result
({&a.) 70 78 78 86 68
FNNVD
({&a.) 72 69 76 76 79
HELLO
NB. encoding result
({&a.) 70 78 78 86 68
FNNVD
Now we can compose and use our encode and decode functions:
encode=:pst@enc@pre
decode=:pst@dec@pre
encode 'PROGRAMMINGPRAXISWITHJ'
OMQNHHQWUIGWRFGSKFOMTP
encode 'PROGRAMMINGPRAXIS'
OMQNHHQWUIGBIMWCS
decode 'OMQNHHQWUIGWRFGSKFOMTP'
PROGRAMMINGPRAXISWITHK
decode 'OMQNHHQWUIGBIMWCS'
PROGRAMMINGPRAXIS
decode=:pst@dec@pre
encode 'PROGRAMMINGPRAXISWITHJ'
OMQNHHQWUIGWRFGSKFOMTP
encode 'PROGRAMMINGPRAXIS'
OMQNHHQWUIGBIMWCS
decode 'OMQNHHQWUIGWRFGSKFOMTP'
PROGRAMMINGPRAXISWITHK
decode 'OMQNHHQWUIGBIMWCS'
PROGRAMMINGPRAXIS
Another example
Not enough? I see you are as fascinated as I am. The next example ist from j602/system/main/convert.ijs
av=: 3 : '({&a.)`(a.&i.) @. (2&=@(3!:0)) y'
3 : '... y' defines a verb, imagine it as a function with one argument y. (()`()@.()) is:
m@.n is a verb defined by the gerund m with an agenda specified by n ; that is, the verb represented by the train selected from m by the indices n . If n is boxed, the train is parenthesized accordingly. The case m@.v uses the result of the verb v to perform the selection.
Pure beauty! Here (2&=@(3!:0)) acts as a case or if expression. It returns a value which becomes the index of the left "list of functions" (take it with salt). 3!:0 returns the "type" (more salt!) of a parameter. If it is a character it returns 2, the following comparison (2&=) returns 1 and (a.&i) evaluates to the index of this character in the ascii table. Otherwise we assume it is a number and return the corresponding character.
(2&=@(3!:0)) 'A'
1
(2&=@(3!:0)) 97
0
({&a.) 99
a
(a.&i.) 'a'
97
({&a.)`(a.&i.) @. (2&=@(3!:0)) 'abc'
97 98 99
({&a.)`(a.&i.) @. (2&=@(3!:0)) 97 98 99
abc
1
(2&=@(3!:0)) 97
0
({&a.) 99
a
(a.&i.) 'a'
97
({&a.)`(a.&i.) @. (2&=@(3!:0)) 'abc'
97 98 99
({&a.)`(a.&i.) @. (2&=@(3!:0)) 97 98 99
abc
Okt 11: Aktualisierung auf xorg-server 1.6
Ging erstaunlich problemlos. Maus und Tastatur waren tot:
Strg+Alt+Rückschritt funktionierte nicht mehr (/etx/X11/xorg.conf)
und >x11-base/xorg-x11-7.4 enthält zuviel Bloat und mußte gehen. xorg-server reicht vollkommen.
Hinweise für die Sachen, die man eh nicht installiert, gibt es wie immer mit:
PS.: qlist ist in portage-utils
sudo emerge -1 $(qlist -IC x11-drivers)
Strg+Alt+Rückschritt funktionierte nicht mehr (/etx/X11/xorg.conf)
Option "XkbOptions" "terminate:ctrl_alt_bksp"
und >x11-base/xorg-x11-7.4 enthält zuviel Bloat und mußte gehen. xorg-server reicht vollkommen.
Hinweise für die Sachen, die man eh nicht installiert, gibt es wie immer mit:
eselect news read new
PS.: qlist ist in portage-utils
Sep 30: ghc unter Gentoo
Das Haskell-Overlay ist schon etwas Feines. Um es zu benutzen benötigt man Darcs, natürlich aus dem Portage-Tree und das wiederum benötigt ghc, den es nur zum stundenlangen Selberbauen gibt, um danach dann die vorkompilierte Variante aus dem Overlay zu installieren, die man eigentlich haben wollte. Ein Traum:
Deshalb hier die Kurzvariante (sudo weggelassen, layman bereits installiert, ghci nicht enthalten):
Das darcs-Binary runterladen und installieren
überprüfen, ob in der /etc/make.conf die make.conf für Layman eingetragen ist
Layman aktualisieren, das Haskell-Overlay hinzufügen und Portage aktualisieren
ghc in der /etc/portage/package.keywords demaskieren
in der /etc/portage/package.use dafür sorgen, daß nicht stundenlang rumkompiliert wird - und ghc braucht wirklich lange
und dann nur noch ghc installieren
Fertig.
Wer eher Komplettpakete mag, könnte gleich die Haskell Platform installieren. Darcs kann jetzt gelöscht oder über das Overlay installiert¹ werden.
¹ Ich mag ja die verteilten Versionsverwaltungen, aber die Vielfalt nervt. Früher reichte svn, heute muß man zusätzlich Git, Mercurial, Darcs und am besten noch Bazaar auf der Platte haben, bloß um an die aktuellen Quelltexte zu kommen.
Total: 10 packages (10 new), Size of downloads: 40,432 kB
Calculating dependencies... done!
[ebuild N ] dev-util/darcs-2.0.2 USE="-doc" 1,759 kB
[ebuild N ] dev-haskell/regex-compat-0.71.0.1 USE="-doc -profile" 4 kB
[ebuild N ] dev-haskell/regex-posix-0.72.0.2 USE="-doc -profile" 42 kB
[ebuild N ] dev-haskell/mtl-1.1.0.0 USE="-doc -profile" 0 kB
[ebuild N ] dev-haskell/html-1.0.1.1 USE="-doc -profile" 11 kB
[ebuild N ] dev-haskell/parsec-2.1.0.0 USE="-doc -profile" 15 kB
[ebuild N ] dev-haskell/quickcheck-1.1.0.0 USE="-doc -profile" 9 kB
[nomerge ] dev-haskell/regex-posix-0.72.0.2 USE="-doc -profile"
[ebuild N ] dev-haskell/regex-base-0.72.0.1 USE="-doc -profile" 7 kB
[ebuild N ] dev-haskell/cabal-1.2.3.0 USE="-doc -profile" 613 kB
[ebuild N ] dev-lang/ghc-6.8.2-r1 USE="-bash-completion -doc -ghcbootstrap" 37,975 kB
Total: 10 packages (10 new), Size of downloads: 40,432 kB
Calculating dependencies... done!
[ebuild N ] dev-util/darcs-2.0.2 USE="-doc" 1,759 kB
[ebuild N ] dev-haskell/regex-compat-0.71.0.1 USE="-doc -profile" 4 kB
[ebuild N ] dev-haskell/regex-posix-0.72.0.2 USE="-doc -profile" 42 kB
[ebuild N ] dev-haskell/mtl-1.1.0.0 USE="-doc -profile" 0 kB
[ebuild N ] dev-haskell/html-1.0.1.1 USE="-doc -profile" 11 kB
[ebuild N ] dev-haskell/parsec-2.1.0.0 USE="-doc -profile" 15 kB
[ebuild N ] dev-haskell/quickcheck-1.1.0.0 USE="-doc -profile" 9 kB
[nomerge ] dev-haskell/regex-posix-0.72.0.2 USE="-doc -profile"
[ebuild N ] dev-haskell/regex-base-0.72.0.1 USE="-doc -profile" 7 kB
[ebuild N ] dev-haskell/cabal-1.2.3.0 USE="-doc -profile" 613 kB
[ebuild N ] dev-lang/ghc-6.8.2-r1 USE="-bash-completion -doc -ghcbootstrap" 37,975 kB
Total: 10 packages (10 new), Size of downloads: 40,432 kB
Deshalb hier die Kurzvariante (sudo weggelassen, layman bereits installiert, ghci nicht enthalten):
Das darcs-Binary runterladen und installieren
cp darcs-2.2.0-ghc6.10-libwww-static.bin /usr/bin/darcs
chmod +x /usr/bin/darcs
chmod +x /usr/bin/darcs
überprüfen, ob in der /etc/make.conf die make.conf für Layman eingetragen ist
source /usr/local/portage/layman/make.conf
Layman aktualisieren, das Haskell-Overlay hinzufügen und Portage aktualisieren
layman --fetch
layman --add haskell
eix-sync
layman --add haskell
eix-sync
ghc in der /etc/portage/package.keywords demaskieren
dev-lang/ghc ~x86
in der /etc/portage/package.use dafür sorgen, daß nicht stundenlang rumkompiliert wird - und ghc braucht wirklich lange
dev-lang/ghc binary
und dann nur noch ghc installieren
emerge ghc
Fertig.
Wer eher Komplettpakete mag, könnte gleich die Haskell Platform installieren. Darcs kann jetzt gelöscht oder über das Overlay installiert¹ werden.
¹ Ich mag ja die verteilten Versionsverwaltungen, aber die Vielfalt nervt. Früher reichte svn, heute muß man zusätzlich Git, Mercurial, Darcs und am besten noch Bazaar auf der Platte haben, bloß um an die aktuellen Quelltexte zu kommen.
« vorherige Seite
(Seite 1 von 5, insgesamt 69 Einträge)
nächste Seite »