invariant invariant update automation
In my everyday job, I often solve the following problem. Due to my contract, I cannot tell you what the exact task is, so I abstracted away the details with the help of category theory.
Let the objects e, i, w be given along with arrows T:w->w, W:e->w, I:e->i. The task is to find an arrow U for which the following diagrams commute:
Let me just name the objects and arrows with real names:
- U – update
- I – invariant projection
- W – window projection
- T – transformation
- w – window
- i – invariant
- e – entity
In other words, I write small automation scripts (U) to update entities represented in quite complex (and distributed) ways, at the same time respecting their consistency and other extra constraints. The task specification (T) usually operates with only a projection/subspace of the real entity space.
check set inclusion with XPath
In the XPath specification, Booleans section, you can read the following sentence about the = operator (in tests):
“If both objects to be compared are node-sets, then the comparison will be true if and only if there is a node in the first node-set and a node in the second node-set such that the result of performing the comparison on the string-values of the two nodes is true. [...]“
Hence you can test for an object being a member of a set of objects:
$ cat data.xml
<root>
<nodes>
<node>3</node>
<node>8</node>
<node>9</node>
<node>2</node>
</nodes>
<ptrs>
<ptr>1</ptr>
<ptr>3</ptr>
</ptrs>
</root>
$ cat selected.xsl
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="//root">
<nodes>
<xsl:for-each select="//root/nodes/node">
<selected>
<xsl:value-of select="position() = //root/ptrs/ptr/text()" />
</selected>
</xsl:for-each>
</nodes>
</xsl:template>
</xsl:stylesheet>
$ xsltproc selected.xsl data.xml | xmllint --format -
<?xml version="1.0"?>
<nodes>
<selected>true</selected>
<selected>false</selected>
<selected>true</selected>
<selected>false</selected>
</nodes>
$
invisible CR
A script of mine stopped working for a set of inputs, the reason behind is below… : D
$ cat i 1 2 3 4 $ cat i | while read i; do echo blah $i; done blah 1 blah 2 blah 3 blah 4 $ cat i | while read i; do echo blah $i foo; done foo 1 foo 2 foo 3 foo 4 $ xxd i 0000000: 310d 0a32 0d0a 330d 0a34 0d0a 1..2..3..4.. $
give yourself a visual glance of your data
You can use GnuPlot with ‘dumb’ terminal setting to just have a really quick look on the data you’re working with..
$ echo $0
-zsh
$ seq -1000 1000 | sed 's.$./1000.' | bc -l > x
$ sed 's/^/e(/' x | sed 's.$.).' | bc -l > y
$ paste x y > f
$ gnuplot <(echo "set term dumb; plot 'f' with dots")
3 ++----------------+----------------+-----------------+---------------++
+ + + + 'f' . +
| ..
2.5 ++ ...+
| ... |
| .... |
| ... |
2 ++ .... ++
| .... |
| .... |
1.5 ++ ..... ++
| .... |
| ..... |
1 ++ ...... ++
| ....... |
| ........ |
| .......... |
0.5 +............ ++
.. |
+ + + + +
0 ++----------------+----------------+-----------------+---------------++
-1 -0.5 0 0.5 1
$
grep multiline entities
In case you have a good separator of multiline entities in a file:
$ ls
update.log
$ cat update.log
Id: 2837
Field1: foo
Field2: bar
Field3: 12.4
---
Id: 44323
Field1: qux
Field2: xxyy
Status: ERROR
Id: 74738
Field1: baz
Field3: boo
$ csplit update.log '/^Id:/' '{*}'
0
51
50
35
$ ls
update.log xx00 xx01 xx02 xx03
$ grep 'Status: ERROR' xx*
xx02:Status: ERROR
$ grep 'Status: ERROR' xx* | cut -d':' -f1 | xargs -n1 head -1
Id: 44323
$
distribution of tablets
I used to consume nicotine tabs (giving up smoking :). I ate a half at a time. When getting a whole tab out, I cut it into two and put a half back. I experienced a higher and higher probability of getting a half during the lifecycle of such a pack. I was curious how this distribution looks like, so asked help from friends regarding the exact math behind and finally got a solution which is like the one below.
Notationally, let n1 denote the number of whole, and n2 the number of half tabs.
Number of whole tabs in step t+1 is n1(t+1), namely you can get a whole or a half (in step t+1), this is respectively:
/ \
n | t | / \
/ \ 1 \ / | / \ |
n | t+1 | = ------------------- | n | t | - 1 | +
1 \ / / \ / \ | 1 \ / |
n | t | + n | t | \ /
1 \ / 2 \ /
/ \
n | t |
2 \ / / \
+ ------------------- n | t |
/ \ / \ 1 \ /
n | t | + n | t |
1 \ / 2 \ /
Equation means that you can get a whole, in this case with n1/(n1+n2) probability. The number of wholes decreases by one (you cut that whole tab into half and put one half back). In the other hand you can draw a half tab with n2/(n1+n2) probability and the number of wholes remains the same (you consume the half).
Doing the same with nr. of half tabs as n2:
/ \
n | t | / \
/ \ 1 \ / | / \ |
n | t+1 | = ------------------- | n | t | + 1 | +
2 \ / / \ / \ | 2 \ / |
n | t | + n | t | \ /
1 \ / 2 \ /
/ \
n | t | / \
2 \ / | / \ |
+ ------------------- | n | t | - 1 |
/ \ / \ | 2 \ / |
n | t | + n | t | \ /
1 \ / 2 \ /
When you get a whole, in this case you put back a half (+1 for the halves). Or a half and you consume that (there’ll be one less).
After some simplification, the equations are like this in differential (&dimensionless) form:
n n - n
. 1 . 1 2
n = - ------ , n = -------
1 n + n 2 n + n
1 2 1 2
Making it simpler (N is the number of tabs, P is the probability you getting a whole):
. . .
N := n + n , NP := n , N-NP = n , n = NP+PN
1 2 1 2 1
. . . . . . . . .
n = N-NP-PN , NP+NP=-P , N-NP-NP = (2NP - N) / N = 2P - 1
2
. . .
N = P - 1 , PP-P+NP=-P , P = - PP/N
Finally:
. . N = P - 1 , P = - PP/N
Solving this numerically with below code and plot it with GnuPlot:
1 #include<iostream>
2
3 int main()
4 {
5 double dt = 1e-3;
6 double N = 1;
7 double P = 1;
8
9 for(double t=0; t<2.0; t+=dt)
10 {
11 std::cout<<t<<" "<<N<<" "<<P<<std::endl;
12 double oN = N;
13 N=N+P*dt-dt;
14 P=P-P*P*dt/oN;
15 }
16
17 return 0;
18 }
command-line (positional) output selector
Sometimes it happens that I work with IDs from entity identifier lists. They have very long ids, there are many of them, but it’s possible to hash them easily with grep resulting a set of cca. 20 from which I can choose visually the one I’m really interested in, although don’t want to type the whole ID for the grep. I used to copy the particular identifier to the clipboard and paste it to the next command line. With this solution below I can explore these sets and work with them without copy-paste (which frequently involved touching the mouse and moving hands away from the keyboard).
$ cat num #!/bin/zsh cat $* | nl -w 3 -n rz $ cat sel #!/bin/zsh cat | grep "^0*$1" | cut -f2- $ demo-query | grep QUX FOO9583749857_BAR_HIOSD57389FJ_QUX__FSKLD FOO9583749857_BAZ9785JFKR_QUX__FSKLD FOO9583749857_QUX__FSKLD_BAR_HIOSD57389FJ FOO9583749857_QUX__FSKLD_BAZ9785JFKR BAR_HIOSD57389FJ_FOO9583749857_QUX__FSKLD BAR_HIOSD57389FJ_BAZ9785JFKR_QUX__FSKLD BAR_HIOSD57389FJ_QUX__FSKLD_FOO9583749857 BAR_HIOSD57389FJ_QUX__FSKLD_BAZ9785JFKR BAZ9785JFKR_FOO9583749857_QUX__FSKLD BAZ9785JFKR_BAR_HIOSD57389FJ_QUX__FSKLD BAZ9785JFKR_QUX__FSKLD_FOO9583749857 BAZ9785JFKR_QUX__FSKLD_BAR_HIOSD57389FJ QUX__FSKLD_FOO9583749857_BAR_HIOSD57389FJ QUX__FSKLD_FOO9583749857_BAZ9785JFKR QUX__FSKLD_BAR_HIOSD57389FJ_FOO9583749857 QUX__FSKLD_BAR_HIOSD57389FJ_BAZ9785JFKR QUX__FSKLD_BAZ9785JFKR_FOO9583749857 QUX__FSKLD_BAZ9785JFKR_BAR_HIOSD57389FJ $ demo-query | grep QUX | num 001 FOO9583749857_BAR_HIOSD57389FJ_QUX__FSKLD 002 FOO9583749857_BAZ9785JFKR_QUX__FSKLD 003 FOO9583749857_QUX__FSKLD_BAR_HIOSD57389FJ 004 FOO9583749857_QUX__FSKLD_BAZ9785JFKR 005 BAR_HIOSD57389FJ_FOO9583749857_QUX__FSKLD 006 BAR_HIOSD57389FJ_BAZ9785JFKR_QUX__FSKLD 007 BAR_HIOSD57389FJ_QUX__FSKLD_FOO9583749857 008 BAR_HIOSD57389FJ_QUX__FSKLD_BAZ9785JFKR 009 BAZ9785JFKR_FOO9583749857_QUX__FSKLD 010 BAZ9785JFKR_BAR_HIOSD57389FJ_QUX__FSKLD 011 BAZ9785JFKR_QUX__FSKLD_FOO9583749857 012 BAZ9785JFKR_QUX__FSKLD_BAR_HIOSD57389FJ 013 QUX__FSKLD_FOO9583749857_BAR_HIOSD57389FJ 014 QUX__FSKLD_FOO9583749857_BAZ9785JFKR 015 QUX__FSKLD_BAR_HIOSD57389FJ_FOO9583749857 016 QUX__FSKLD_BAR_HIOSD57389FJ_BAZ9785JFKR 017 QUX__FSKLD_BAZ9785JFKR_FOO9583749857 018 QUX__FSKLD_BAZ9785JFKR_BAR_HIOSD57389FJ $ demo-query | grep QUX | num | sel 12 BAZ9785JFKR_QUX__FSKLD_BAR_HIOSD57389FJ $ demo-query | grep QUX | num | sel 12 | xargs find . -name ./AB/BAZ9785JFKR_QUX__FSKLD_BAR_HIOSD57389FJ ./EG/UI/BAZ9785JFKR_QUX__FSKLD_BAR_HIOSD57389FJ $
iPhone app dev; first steps; concentration meter
I proudly announce my first iPhone app. It’s called ConMeter (for Concentration Meter). It’s good to give some quantitative view on your current mental state regarding concentration abilities. It displays color names written with colored fonts in a sequence. You have to say yes for a screen on which there’s a color appearing also on the previous screen (as word or font color). For example:
SCREEN1: RED written, BLUE letters SCREEN2: BLUE written, YELLOW letters SCREEN3: GREEN written, BLACK letters
on SCREEN2, there’s BLUE which appears also on SCREEN1, so you have to answer Yes on SCREEN2, but on SCREEN3. On SCREEN3, there’s no such color which appears on SCREEN2.
one of my favourite quotes
Lawrence Baird: I'm Dr. Lawrence Baird. Psychiatrist: I hear you. I hear you saying you're Dr. Lawrence Baird. Lawrence Baird: I am Dr. Baird, though. I really am. I'm Dr. Baird. Psychiatrist: I hear you. I really do. I hear you saying, "I am Dr. Baird." Lawrence Baird: You're not really listening to me. You think you're hearing what I'm saying...
cobol hello world @ http://rzkh.de/
This is an AS/400 system called RZKH. I registered with an account and sorted out how to write and compile a cobol program (hello world here). The motivation was this article : ) On AS/400, there’s a quite good menu system and PDM which is an IDE.. My intent was to perform the session without those and use the commands. There’s no reason for this latter : ) Additionally, I wanted to use COBOL in one of its inherent environments.




