Tag Archive for "misc" tag

HQ9+, H9+, KL esoterical languages and the beer song

April 4th, 2011 by Ivan Lakhturov | 0 Category: Programming | Tags: |

Let's first sing a beer song (in R6RS Scheme):

  1. #!r6rs
  2. (library (sing-beer-song)
  3.          (export sing-beer-song)
  4.          (import (rnrs))
  5.  
  6.          (define (sing-beer-song n)
  7.            (define (n-bottles i capital?)
  8.              (string-append
  9.               (cond
  10.                 ((eqv? i -1) (number->string 99))
  11.                 ((and (eqv? i 0) capital?) "No more")
  12.                 ((eqv? i 0) "no more")
  13.                 (else (number->string i)))
  14.               " bottle" (if (eqv? i 1) "" "s")
  15.               " of beer"))
  16.            (define (where?) " on the wall")
  17.            (define (what-to-do? n)
  18.              (if (> n 0) "Take one down and pass it around, "
  19.                  "Go to the store and buy some more, "))
  20.            (string-append
  21.             "\n" (n-bottles n #t) (where?) ", " (n-bottles n #f) ".\n"
  22.             (what-to-do? n) (n-bottles (- n 1) #f) (where?) ".\n"
  23.             (if (> n 0) (sing-beer-song (- n 1)) ""))))

Then let's make an extra library:

  1. #!r6rs
  2. (library (language-utilities)
  3.          (export glue)
  4.          (import (rnrs))
  5.  
  6.          (define (glue los) (fold-left string-append "" los)))

... and we are ready to write yet-another HQ9+ interpreter:

  1. #!r6rs
  2. (import (rnrs) (sing-beer-song) (language-utilities))
  3.  
  4. ; HQ9+ interpreter v0.1 (Ivan Lakhturov)
  5. ; http://esolangs.org/wiki/HQ9
  6.  
  7. (define i 0)
  8.  
  9. (define (run-program s)
  10.   (define (run-command c)
  11.     (cond
  12.       ((eqv? c #\H) "Hello, World!")
  13.       ((eqv? c #\Q) s)
  14.       ((eqv? c #\9) (sing-beer-song 99))
  15.       ((eqv? c #\+) (set! i (+ i 1)) "") ; (number->string i))
  16.       (else (string c))))
  17.   (glue (map run-command (string->list s))))  
  18.  
  19. (display (run-program "HQ9+"))

HQ9+ is a joke language, featuring "Hello world" command, quine command, beer-song command and a counter increment (counter cannot be accessed or printed out). Quine implementation here is the classical "quine-cheating", where a program has access to its source. To make the quine more 'honest' somebody designed H9+. This is the same as HQ9+, but without "Q" command, and additionally, all characters on input are ignored, except for H, 9 and +. Then, obviously, "Hello, World!" program will be a quine. Let's implement H9+:

  1. #!r6rs
  2. (import (rnrs) (sing-beer-song) (language-utilities))
  3.  
  4. ; H9+ interpreter v0.1 (Ivan Lakhturov)
  5. ; http://esolangs.org/wiki/H9
  6.  
  7. (define i 0)
  8.  
  9. (define (run-program s)
  10.   (define (run-command c)
  11.     (cond
  12.       ((eqv? c #\H) "Hello, World!")
  13.       ((eqv? c #\9) (sing-beer-song 99))
  14.       ((eqv? c #\+) (set! i (+ i 1)) "") ; (number->string i))
  15.       (else "")))
  16.   (glue (map run-command (string->list s))))  
  17.  
  18. (display (run-program "Hello, World!"))

And let's implement also a variation of this theme, the esoterical language KL:

  1. #!r6rs
  2. (import (rnrs) (language-utilities))
  3.  
  4. ; KL interpreter v0.1 (Ivan Lakhturov)
  5. ; http://ivanguide.ru/kl/
  6.  
  7. (define (run-program s)
  8.   (define (run-command c)
  9.     (cond
  10.       ((eqv? c #\+) "Привет, мир!")
  11.       ((eqv? c #\-) s)
  12.       ((eqv? c #\*)
  13. "Я узнал, что у меня
  14. Есть огpомная семья –
  15. И тpопинка, и лесок,
  16. В поле каждый колосок!
  17.  
  18. Речка, небо голубое –
  19. Это все мое, pодное!
  20. Это Родина моя!
  21. Всех люблю на свете я!")
  22.       ((eqv? c #\/) "\n")
  23.       (else (string c))))
  24.   (glue (map run-command (string->list s))))  
  25.  
  26. (display (run-program "+/-/*/extras"))

The semantics is as following: + is printing "Hello, world!" in Russian, - is printing a program's source, / is making a newline, and * print outs a poem from Russian movie "Brother".

To complete the picture, we can mention other close related to HQ9+ joke languages: HQ9++, CHIQRSX9, HQ9+B, HQ9+2D. HQ9++ is 'an object-oriented extension of HQ9+'; not interesting. CHIQRSX9+ adds eval, ROT-13 and sorting of input lines. ROT-13 (Caesar cipher) is a nice exercise to implement, but let's leave it for later. HQ9+B adds Brainfuck: this is definitely a thing to implement, but I will deal with Brainfuck later. HQ9+2D is not properly specified (even for a joke language), but commands it adds remind me 2D Turing-machine, so called Langton's ant. I want to implement and play with different Turing-machines, but later.

Later I will also look through the list of joke languages. For example, the first there is a 'language' 99, which just prints out '99 bottles of beer' song. Anyways, I hope, there could be something exciting in the list.

Aerodynamic calibration rig

October 6th, 2010 by Ivan Lakhturov | 0 Category: Programming | Tags:

More than five years ago I worked for "DX-Complexes" and "Spectromed-UA". Here is a video about one of the projects I accomplished there. This is the aerodynamic calibration rig for metrological testing of spirographs. (What is a spirograph? See spirometry topic at Wikipedia).

http://www.youtube.com/watch?v=y4KBf_SQJhk

There is no sound in this video, cause we wanted to make a promo-video out of this, and some voiceover was supposed to be done later. But the device was too specialized, so we decided not to. So, let it be an advertisement for myself.

The schematics is in the illustration:

I operate the control program, written in C#, which communicates by COM-port with the embedded program in C. Both are written by me. Then this embedded program drives the device you see on video. It consists of electronics, the engine, worm gear and a piston going forwards and backwards in a plexiglass cylinder. The air flow generated by the device is registered with a spyrograph, connected via USB-port to another PC, where a third-party spirometry program is installed (visible in the second part of video).

Naturally, to verify the accuracy of a spiro-device, the calibration rig has to be in sctrict accuracy limits itself. It wasn't so trivial to achieve those specs. I remember one of the problems with overjumps: when you turn off the power of an engine, the piston doesn't stop momentarily due to inertia and slips further. What's the solution? To apply maximal reverse force via the engine as soon as the piston is supposed to stop. A period of time when we apply that reverse force depends on a few hard-to-estimate factors, so it was easier to fit this empirically.

This device can be considered as a very simple 'robot' with just one degree of freedom. Despite simplicity, it took us (2 people, me for software and a colleague for electronics and mechanics) around half a year of occasional work to get it done. Nevertheless, my friends in Ukraine report this device is still in field, they use it up to now without any complaints rising.

Real-time ECG-generator

July 28th, 2009 by Ivan Lakhturov | 0 Category: Programming | Tags:

Some years ago I accomplished a project of the real-time ECG-generator (the text is in Russian) for Spectromed-UA. I wrote a soft part in Delphi, and another guy dealt with an electronics part.

The device is connected to PC and sends out a signal via LPT to a DAC outside. A signal could be rectangular (meander), sinusoidal and ECG-like. (ECG is the electrocardiogram by the way). The 'heartbeat' of the latest one can be modulated in time. A subprogram to play out real ECG was included. Some noise modulation was included as well.

That was designed to test cardio-analyzers and similar devices. Small and neat project, as I remember. There was no support for the most pathological arrhythmias, however.

All subsets of a set

July 2nd, 2009 by Ivan Lakhturov | 3 comments Category: Programming | Tags: |

As I already posted in Scheme, a function computing all subsets of a set would be:

  1. #!r6rs
  2. (import (rnrs))
  3.  
  4. (define (subsets set)
  5.   (define (recursion set rest) (if (null? set) (list rest)
  6.                                    (let ([head (car set)] [tail (cdr set)])
  7.                                      (append (recursion tail rest) (recursion tail (cons head rest))))))
  8.   (recursion set '()))
  9.  
  10. (display (subsets '(a b c d)))

The same in Haskell:

  1. s = "abcd"
  2.  
  3. subsets s = ssets (s) []
  4. ssets [] r = [reverse(r)]
  5. ssets (x:xx) r = ssets xx r ++ ssets xx (x:r)
  6.  
  7. main = do
  8.         putStrLn " Set: "
  9.         print s
  10.        
  11.         putStrLn " Subsets: "
  12.         print (subsets s)

For imperative languages I'd rather prefer bitwise approach. Here is in C#:

  1. using System;
  2.  
  3. namespace Subsets
  4. {
  5.     class Program
  6.     {
  7.         static void Main()
  8.         {
  9.             string elements = "abcd";
  10.             for (ulong i = 0; i < Math.Pow(2, elements.Length); i++)
  11.             {
  12.                 ulong set = i;
  13.                 for (int j = 0; j < elements.Length; j++, set >>= 1)
  14.                     if ((set & 0x01) == 1)
  15.                         Console.Write(elements[j]);
  16.                 Console.WriteLine();
  17.             }
  18.         }
  19.     }
  20. }

Basic laptop maintenance

March 31st, 2009 by Ivan Lakhturov | 0 Category: Miscellaneous | Tags: |

Some months ago my notebook began to overheat. When the CPU is loaded enough, its temperature grows over 95 degrees Celsius, and a guard mechanism throttles down its frequency to 40 % and waits until it cools down. Within a few minutes the system is badly responsive.

I bought a cooling platform for it, but with time it couldn't restrain the heat. A problem became worse and worse, but the warranty for the laptop was void already. So, I took a screwdriver and solved it:

A dense layer of dust covered the radiator and prevented air flow. Now under 100 % load my CPU is cool enough. I mean, for a Turion --- 80 degrees Celsius for the general sensor, 85 for the first core, and 91-93 for the second one (sitting on a table, without a cooling platform). Strange gradient, but anyway, a system doesn't freeze now.