Turingmaskin

Under julen skrev jag en liten Turingmaskin och ett program till den som implementerar addition av två 7 bitars binära tal på den. Med hjälp av den kod som finns i additionen finns allt som behövs för att också implementera subtraktion, multiplikation och division samt modulo, men det lämnar jag till något annat tillfälle.

Koden finns här för den som är intresserad. Själva Turingmaskinen består av mindre än 100 rader kod och är implementerad i python. Maskinen har ett register som börjar på noll och kan gå till minus oändligheten och till plus oändligheten. Den har också ett läs/skrivhuvud samt en kortläsare som kan läsa in programkod. Korten innehåller sex rader och ger instruktioner för vad maskinen ska göra om den läser en nolla i registret respektive vad den ska göra om den läser en etta. Möjliga handlingar är att skriva en nolla eller en etta. I kortet finns också instruktioner till vilket som är nästa kort beroende på om den läste en etta eller en nolla.
Själva additionen görs ganska enkelt och är implementerad i 88 kort. Algoritmen ser ut som följer:

Först går den till den negativa sidan av registret och fyller i ettor motsvarande det första talet som ska adderas till det andra, sedan går det till den positiva sidan av registret och fyller i den andra talet. Det första talet lagrar alltså sina bitar binärt i registerposition -1 till -8 (det riskerar förstås att bli overflow om alla bitar används på båda sidor) medan det andra talet finns på register position 1 till 8. Därefter rör sig läshuvudet tillbaka till position noll och räknar ned talet på den negativa sidan med ett. Nedräkningen görs genom att om läshuvudet ser en etta så skriver den en nolla och går tillbaka till position noll, om den tvärt om ser en nolla så går den till nästa bit och upprepar samma sak. Om den inte sett någon etta när den kollat hela vägen bort till position -8 så är talet noll och det har då blivit overflow vilket vi kommer utnyttja senare för att avsluta vår algoritm. När den räknat ned talet på den negativa sidan så adderar den ett till talet på den positiva sidan. Det sker på samma sätt som nedräkning, fast tvärt om. Om läshuvudet ser en etta så skriver den en nolla och fortsätter bort i registret, om den ser en nolla så skriver den en etta och går tillbaka till position noll. Sedan fortsätter läshuvudet på detta sätt att räkna ned på ena sidan och räkna upp på den andra tills alla bitar är slut på den negativa sidan och läshuvudet har läst förbi talet där. Då avslutas algoritmen och hela det adderade talet finns i registret på position 1 till 8 på den positiva sidan, så läshuvudet läser helt enkelt ut svaret som stå där.

Det är lätt att först att addera 1 till ett tal lika många gånger som värdet på ett annat tal är det samma som att addera dessa två tal, 2 + 2 är det samma som 1 + 1 + 2. Om man i stället skulle ha dragit ifrån en för varje så skulle man på det sättet ha implementerat subtraktion, 2 -2 är det samma som 2 -1 -1. Genom att ha en andra räknare på den negativa sidan så skulle man kunnat ha implementerat multiplikation, 4 * 4 är det samma som 1 + 1 + 1 + 1 + 1 + 1 + 1 +1 + 1 + 1 + 1 + 1 + 4. Detta skulle också ha möjliggjort division, eftersom division bara skulle innebära att räkna hur många gånger man behöver addera ett tal (nämnaren) till sig själv innan man uppnått den efterfrågade summan (täljaren).

Perlscript för att expandera en ipv6-adress

Håller på att kika lite på perl som jag inte kodat så mycket i tidigare. Skrev då ett script som expanderar en ipv6-adress som ju kan ha en variabel mängd 0:or, t.ex. är både ::1 och 0000:0000:0000:0000:0000:0000:0000:0001 en helt ok ipv6-adress som båda expanderar till samma sak.

#!/usr/bin/env perl
use strict;
use warnings;
sub count_groups { # See hown many groups we have
        die "Too many arguments for subroutine" if @_ < 1;
        die "Too few arguments for subroutine" if @_ > 1;
        my $address = shift;
        # Make sure we have just enough double colons and count them if it is all right
        my $colon_no =  () = $address =~ /::/g;
        die "Invalid ipv6 address" if $colon_no > 1;
        my $no =  1;
        $no += () = $address =~ /:/g;
        return $no;
}
# If we have one occurence of :: replace with correct amount of zeros and colons
sub expand_void {
        die "Too many arguments for subroutine" if @_ < 1;
        die "Too few arguments for subroutine" if @_ > 1;
        my $address = shift;
        my $no_colons = 8 - count_groups($address);
        my $insert = "0000:0000";
        for (my $i = 0; $i < $no_colons - 1; $i++) {
                $insert = $insert . ":0000"
        }
        $address =~ s/::/:$insert:/g;
        return $address;
}
# Fix a single group and padd with zeros
sub fix_group {
        die "Too many arguments for subroutine" if @_ < 1;
        die "Too few arguments for subroutine" if @_ > 1;
        my $group = shift;
        my $len = length($group);
        die "Group has too many digits" if $len > 4;
        while ($len < 4) {
                $group = "0$group";
                $len++;
        }
        # Make sure it is a valid hexnumber
        die "Group is not a hex number" if $group !~ /^[0-9a-fA-F]+$/;
        return $group;
}
# Loop all groups and fix them with fix_group
sub fix_groups {
        die "Too many arguments for subroutine" if @_ < 1;
        die "Too few arguments for subroutine" if @_ > 1;
        my $a = shift;
        my @groups = split(/:/, $a);
        my $address = "";
        foreach my $group (@groups) {
                $group = fix_group($group);
                $address = "$address$group:";
        }
        $address =~ s/:+$//;
        return $address;
}
# Now put it together
# Loop through stdin
while (<>) {
        chomp; # Remove newline
        my $addr = $_; # Store address
        if (count_groups($addr) != 8) {
                $addr = expand_void($addr);
        }
        $addr = fix_groups($addr);
        # Double check that we have enough groups one last time
        die "Not a valid ipv6 address" if count_groups($addr) != 8;
        # Lower case is preffered for ipv6 adresses
        print lc "$addr\n";
}
exit 0;

Kan användas t.ex. så här för att expandera dina egna ipv6-adresser: ip a | awk '/inet6/ {print $2}' |sed 's_/.*__' | ./address.pl

eller för att t.ex. bygga reverse pointers: echo [adress] | ./address.pl |rev |sed 's/://g'| sed 's/\(.\)/\1./g' | sed 's/$/ip6.arpa. IN PTR/'

Odlingslåda för inomhusbruk

Idag har jag byggt en odlingslåda för inomhusbruk. Tanken är att jag ska kunna odla lite grönsaker även under vintern, när det blivit för kallt på balkongen.

2015-08-29 17.16.14

Den har just nu en odlingslampa, i framtiden kommer den ha två stycken, som hänger närmare tvärbalken och som därför får lite mer fri höjd. Tvärbalken sitter med klämmor och kan flyttas upp och ned efter behov för övrigt. I botten på lådan finns ett vattenmagasin som är fyllt med lecakulor och som det går ned två tjocka rör i, så att det inte ska vara så kinkigt med att komma i håg att vattna. Den ska vara själv-vattnande.

Jag fick inspiration från den här videon:


Så här kan du göra för att bygga en egen.

Inköpslista

De här sakerna använde jag. Artikelnummer inom parentes.

Biltema
  • 1st Plastförvaringslåda 70 liter, med hjul (28442) – ytterlådan
  • 1st Förvaringslåda plast, 47 liter (28441) – innerlådan
  • 2st Anslutningsrör vitt 104/97mm – där vattnet ska nå växterna
  • 1st Avloppsrör (87252) – för att kolla vattennivå och fylla på vatten
  • 1st Rörisolering för 12mm rör (860018) – vattennivå mätare
Clas Ohlson
  • 2st Klädstång 25 mm (40-8208) – fäste för belysning
  • 1st Aluminiumprofil (41-2692) – tvärbalk för belysning
  • 1st Buntbandsats (36-3442) – diverse fästningar
  • 2st Universalklämma 100 mm (40-7212) – fäste av tvärbalk
  • 2st Växtlampa LED (36-1324) – belysning
Bauhaus
  • Weibulls lecakulor (6400893A) – åtgång ca 23 liter
  • Grönsaksjord (6999556A) – åtgång ca 40 liter eller något mer
Övrigt
  • Markduk, genomsläpplig. Jag hade en skarvbit hemma som jag använde. Tror att det var metervara inköpt på bauhaus, men inte helt säker.
  • Råkade köpa fel armaturer för lamporna, så två stycken lampor som kan hängas från tvärbalken, som har stickpropp och E27-sockel behövs.

Totalkostnad för inköpen är 1311,45 varav 198 är jord och lecakulor och 498 är växtlamporna.

2015-08-29 15.28.36

För ihopsättningen behövdes också lite verktyg.

  • Tumstock
  • Tuschpenna
  • Sax
  • Bågfilar
  • Mattkniv

2015-08-29 17.02.22

Börja med att rita ut var du ska skära ut/såga upp för rören. Den smalare änden av anslutningsröret ska sticka upp underifrån i 47-liters plastbacken och avloppsröret ska gå ned i ena kanten.

2015-08-29 15.43.08

Rita ut var du ska göra hål och såga sedan försiktigt upp hålen. Plastbacken var mycket spröd och sprack flera gånger för mig. Det gjorde inget eftersom den ska stå på lecakulor och ha markduk på ovansidan, men det skadar inte att ta det lungt när du gör hål. Borra också små hål, ca 20 st jämt fördelade över backens undersida.

2015-08-29 16.03.01

För att vatten ska kunna komma upp i rören behöver du såga ut lite jack i anslutningsröret. Det gäller även nederdelen på avloppsröret.

2015-08-29 15.55.31

För utom hål där vatten kan rinna ned, behöver du också mäta ut mitten på kortsidorna och sedan borra tre par hål på varje sida där du sedan ska spänna fast rören som ska hålla uppe ljusanordningen. Borra även två hål som du kan använda att spänna fast avloppsröret med högst uppe i det hör där avloppsröret ska gå.

2015-08-29 16.02.52

Nu kan du tejpa fast anslutningsröer i botten på den större hjulförsedda backen. Du kan med fördel sätta in anslutningsrören i hålen som du sågat ut, ställa ned hela den mindre lådan med rörer i den större plastbacken och sedan rita ut på den större var det är tänkt att de sak stå, så står de på rätt plats när du ska försöka passa in allt efter att du fyllt på lecakulor.

2015-08-29 15.56.40

Nästa steg är att stoppa lite markduk i botten på rören och fylla på med lecakulor.

2015-08-29 16.08.24

Tänk på att du ska få plats med avloppsöret också. Jag valde att ha kvar den delen av avloppsröret som är tjockare upptill. Om du gör på samma sätt, tänk på att du inte då kan tejpa fast avloppsröret på sin plats innan du fyller lecakulor, utan du måste trycka ned röret genom botten sedan. Jag satte därför ett litet hoprullat rör av tunn plast i ena hörnet som jag sedan, efter att jag satt i avloppsröret i den kunde dra ut genom de större hålen för anslutningsrören.

2015-08-29 16.21.12

När det är påfyllt med lecakulor så spänner du fast klädstängerna på insidan av den mindre backen genom hålen du borrade tidigare, trär ned den i den större backen och trycker ned avloppsröret genom hålet. Avloppsröret måste du förstås såga av till lämplig längd först. Jag sågade av den så att röret blev lika lång som den större backen var hög + ca 5 cm.

2015-08-29 16.23.04

Se till så att allt är ordentligt fastspänt med buntband, klipp av flärparna och lägg i lite markduk i botten på backen. Det är viktigt att du klipper hål i den så att jorden fritt kan åka ned i anslutningsrören, se dock till så att det ligger lite markduk i botten på anslutningsrören också. Såga av aluminiumprofilen så att den blir lika lång som det är mellan klädstängerna på det bredaste stället.

2015-08-29 16.29.34

Nu är det bara att fylla på jord, vattna och fästa aluminiumprofilen på klädstängerna med klämmor och därefter fästa belysningen med buntband. Klipp av en bit rörisolering så att den blir lika lång som avloppsröret och lägg i den i röret. När du fyller på vatten kommer den att flyta upp och indikera hur vattennivån ser ut. Du kan även vattna genom avloppsröret om du lyfter undan rörisoleringen. Fyll inte på vatten så att det går över lecakulorna. Om du häller på för mycket vatten kan du slanga ut det igen genom avloppsröret.

2015-08-29 17.15.53

Nu är du klar!

Installera Oracles java i Linux

Oracle har gjort det svårt för linuxdistributioner att ha java i sina repositories sedan de köpte Sun. Icke desto mindre behövs i bland Oracles javaversion när openjdk inte räcker för någon specifik implementation. Jag kommer därför visa hur du kan göra för att installera Oracles java på ett sätt som underlättar framtida uppdateringar. Säkerhetsbrister i java är nämligen den attackvektor som används vid närmare 90% av alla lyckade intrång på en persondator vilket gör att det är viktigt att uppgradera varje gång Oracle släpper patchar, även när du inte installerar via en pakethanterare.

Jag kommer här gå igenom installation av 64 bitars java, om du ska köra 32 bitar på ett 64 bitars OS behöver du installera en version av glibc för i386 samt använda nspluginwrapper för att gör browserpluginet tillgängligt. Det är lite bökigare så jag kommer inte gå igenom det här, men det går att göra.

Alla kommandon nedan körs som root, tills jag säger till.

Börja med att ta bort andra installationer av java du kan ha (exempel för debianbaserade distar):

apt-get purge oracle-java*
apt-get purge openjdk*

gå till:
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

Godkänn oracles licensavtal och ladda ned senaste sdk:n, här nedan antar jag att du sparar filen i /tmp. Den fil jag laddade hem hette jdk-8u11-linux-x64.tar.gz, din kommer förmodligen ha en annan versionsnumrering så uppdatera kommandona nedan så att du får rätt sökvägar.

Vi kommer nu att skapa en katalogstruktur under /opt som gör de lätt för oss att uppgradera java i framtiden, därefter kommer vi symlänka till binärerna under /usr/bin/ (om du mår bättre av det kan du förstås köra /usr/local/bin/ istället) och lägga en länk till browserpluginet på rätt ställe för firefox, Google har valt att inte stödja NPAPI för Chrome sedan version 35 vilket gör att det inte kommer funka för Chrome.

mkdir /opt/java/
cd /opt/java/
mv /tmp/jdk-8u11-linux-x64.tar.gz .
tar xfv jdk-8u11-linux-x64.tar.gz
ln -s jdk1.8.0_11 latest
ln -s latest default

Av någon anledning har Oracle ägaren med uid 10 (uucp på flera distar) på sina filer, men jag byter dem alltid till root:

chown -R -h root:root *

Nu kan vi börja skapa symlänkar. Jag brukar bara använda binärerna java, javac, javadoc och javaws så vi kör dem först:

ln -s /opt/java/default/bin/java /usr/bin/
ln -s /opt/java/default/bin/javac /usr/bin/
ln -s /opt/java/default/bin/javadoc /usr/bin/
ln -s /opt/java/default/bin/javaws /usr/bin/

Om du vill kan du även köra resten av binärerna:

ln -s /opt/java/default/bin/appletviewer /usr/bin/
ln -s /opt/java/default/bin/ControlPanel /usr/bin/
ln -s /opt/java/default/bin/extcheck /usr/bin/
ln -s /opt/java/default/bin/idlj /usr/bin/
ln -s /opt/java/default/bin/jar /usr/bin/
ln -s /opt/java/default/bin/jarsigner /usr/bin/
ln -s /opt/java/default/bin/javafxpackager /usr/bin/
ln -s /opt/java/default/bin/javah /usr/bin/
ln -s /opt/java/default/bin/javap /usr/bin/
ln -s /opt/java/default/bin/java-rmi.cgi /usr/bin/
ln -s /opt/java/default/bin/jcmd /usr/bin/
ln -s /opt/java/default/bin/jconsole /usr/bin/
ln -s /opt/java/default/bin/jcontrol /usr/bin/
ln -s /opt/java/default/bin/jdb /usr/bin/
ln -s /opt/java/default/bin/jdeps /usr/bin/
ln -s /opt/java/default/bin/jhat /usr/bin/
ln -s /opt/java/default/bin/jinfo /usr/bin/
ln -s /opt/java/default/bin/jjs /usr/bin/
ln -s /opt/java/default/bin/jmap /usr/bin/
ln -s /opt/java/default/bin/jmc /usr/bin/
ln -s /opt/java/default/bin/jmc.ini /usr/bin/
ln -s /opt/java/default/bin/jps /usr/bin/
ln -s /opt/java/default/bin/jrunscript /usr/bin/
ln -s /opt/java/default/bin/jsadebugd /usr/bin/
ln -s /opt/java/default/bin/jstack /usr/bin/
ln -s /opt/java/default/bin/jstat /usr/bin/
ln -s /opt/java/default/bin/jstatd /usr/bin/
ln -s /opt/java/default/bin/jvisualvm /usr/bin/
ln -s /opt/java/default/bin/keytool /usr/bin/
ln -s /opt/java/default/bin/native2ascii /usr/bin/
ln -s /opt/java/default/bin/orbd /usr/bin/
ln -s /opt/java/default/bin/pack200 /usr/bin/
ln -s /opt/java/default/bin/policytool /usr/bin/
ln -s /opt/java/default/bin/rmic /usr/bin/
ln -s /opt/java/default/bin/rmid /usr/bin/
ln -s /opt/java/default/bin/rmiregistry /usr/bin/
ln -s /opt/java/default/bin/schemagen /usr/bin/
ln -s /opt/java/default/bin/serialver /usr/bin/
ln -s /opt/java/default/bin/servertool /usr/bin/
ln -s /opt/java/default/bin/tnameserv /usr/bin/
ln -s /opt/java/default/bin/unpack200 /usr/bin/
ln -s /opt/java/default/bin/wsgen /usr/bin/
ln -s /opt/java/default/bin/wsimport /usr/bin/
ln -s /opt/java/default/bin/xjc /usr/bin/

För att få browserpluginet att funka kör vi nu:

ln -s /opt/java/default/jre/lib/amd64/libnpjp2.so /usr/lib/mozilla/plugins/

Om du behöver kan du nu också sätta JAVA_HOME i din .bash_rc, kör detta som din egen användare (inte root)

echo "JAVA_HOME=/opt/java/default
export JAVA_HOME" >> ~/.bash_rc

Nästa gång du behöver uppgradera java laddar du bara hem en ny version från oracle och packar upp den i /opt/java och pekar om symlänken /opt/java/latest från /opt/java/jdk1.8.0_11 till din nya katalog och du är klar.

En snabb trafikräknare för apache

I dag ville jag räkna antal unika besökare till en ny site jag satt upp. Så här gjorde jag:

#!/bin/bash
if [[ -z "$1" ]]; then
        date=$(date +%d/%b)
else
        date=$(date -d "$1" +%d/%b)
fi
zcat /var/log/apache2/access.log*.gz | cat - /var/log/apache2/access.log{,.1} | grep -i $date  | awk '{print $1}' | sort | uniq | wc -l
exit 0

Skriptet tar en frivillig parameter som är ett datum som date-kommandot kan parsa och räknar antal unika ipadresser i logiflen för det datumet. Utan parameter får du dagens besökare.

Edit: Fixade så att gzipade loggar kom med också.

Switch to our mobile site

Page optimized by WP Minify WordPress Plugin