Task: Morse code




Go: 


package main

import (
	"flag"
	"fmt"
	"log"
	"regexp"
	"strings"
	"syscall"
	"time"
	"unicode"
)



type key struct {
	duration int
	on       bool
	sym      string 
}

var (
	runeToKeys   = map[rune][]key{}
	interCharGap = []key{{1, false, ""}}
	punctGap     = []key{{7, false, " / "}}
	charGap      = []key{{3, false, " "}}
	wordGap      = []key{{7, false, " / "}}
)

const rawMorse = `
A:.-    J:.---  S:...    1:.----  .:.-.-.-  ::---...
B:-...  K:-.-   T:-      2:..---  ,:--..--  ;:-.-.-.
C:-.-.  L:.-..  U:..-    3:...--  ?:..--..  =:-...-
D:-..   M:--    V:...-   4:....-  ':.----.  +:.-.-.
E:.     N:-.    W:.--    5:.....  !:-.-.--  -:-....-
F:..-.  O:---   X:-..-   6:-....  /:-..-.   _:..--.-
G:--.   P:.--.  Y:-.--   7:--...  (:-.--.   ":.-..-.
H:....  Q:--.-  Z:--..   8:---..  ):-.--.-  $:...-..-
I:..    R:.-.   0:-----  9:----.  &:.-...   @:.--.-.
`

func init() {
	
	r := regexp.MustCompile("([^ ]):([.-]+)")
	for _, m := range r.FindAllStringSubmatch(rawMorse, -1) {
		c := m[1][0]
		keys := []key{}
		for i, dd := range m[2] {
			if i > 0 {
				keys = append(keys, interCharGap...)
			}
			if dd == '.' {
				keys = append(keys, key{1, true, "."})
			} else if dd == '-' {
				keys = append(keys, key{3, true, "-"})
			} else {
				log.Fatalf("found %c in morse for %c", dd, c)
			}
			runeToKeys[rune(c)] = keys
			runeToKeys[unicode.ToLower(rune(c))] = keys
		}
	}
}


func MorseKeys(in string) ([]key, error) {
	afterWord := false
	afterChar := false
	result := []key{}
	for _, c := range in {
		if unicode.IsSpace(c) {
			afterWord = true
			continue
		}
		morse, ok := runeToKeys[c]
		if !ok {
			return nil, fmt.Errorf("can't translate %c to morse", c)
		}
		if unicode.IsPunct(c) && afterChar {
			result = append(result, punctGap...)
		} else if afterWord {
			result = append(result, wordGap...)
		} else if afterChar {
			result = append(result, charGap...)
		}
		result = append(result, morse...)
		afterChar = true
		afterWord = false
	}
	return result, nil
}

func main() {
	var ditDuration time.Duration
	flag.DurationVar(&ditDuration, "d", 40*time.Millisecond, "length of dit")
	flag.Parse()
	in := "hello world."
	if len(flag.Args()) > 1 {
		in = strings.Join(flag.Args(), " ")
	}
	keys, err := MorseKeys(in)
	if err != nil {
		log.Fatalf("failed to translate: %s", err)
	}
	for _, k := range keys {
		if k.on {
			if err := note(true); err != nil {
				log.Fatalf("failed to play note: %s", err)
			}
		}
		fmt.Print(k.sym)
		time.Sleep(ditDuration * time.Duration(k.duration))
		if k.on {
			if err := note(false); err != nil {
				log.Fatalf("failed to stop note: %s", err)
			}
		}
	}
	fmt.Println()
}



var consoleFD uintptr

func init() {
	fd, err := syscall.Open("/dev/console", syscall.O_WRONLY, 0)
	if err != nil {
		log.Fatalf("failed to get console device: %s", err)
	}
	consoleFD = uintptr(fd)
}

const KIOCSOUND = 0x4B2F
const clockTickRate = 1193180
const freqHz = 600


func note(on bool) error {
	arg := uintptr(0)
	if on {
		arg = clockTickRate / freqHz
	}
	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, consoleFD, KIOCSOUND, arg)
	if errno != 0 {
		return errno
	}
	return nil

}








Ada: package Morse is

   type Symbols is (Nul, '-', '.', ' ');
   
   Dash : constant Symbols := '-';
   Dot : constant Symbols := '.';
   type Morse_Str is array (Positive range <>) of Symbols;
   pragma Pack (Morse_Str);

   function Convert (Input : String) return Morse_Str;
   procedure Morsebeep (Input : Morse_Str);

private
   subtype Reschars is Character range ' ' .. 'Z';
   
   subtype Length is Natural range 1 .. 5;
   subtype Codes is Morse_Str (Length);
   
   

   type Codings is record
      L : Length;
      Code : Codes;
   end record;
   Table : constant array (Reschars) of Codings :=
     ('A' => (2, ".-   "), 'B' => (4, "-... "),  'C' => (4, "-.-. "),
      'D' => (3, "-..  "), 'E' => (1, ".    "),  'F' => (4, "..-. "),
      'G' => (3, "
      'J' => (4, ".
      'M' => (2, "
      'P' => (4, ".
      'S' => (3, "...  "), 'T' => (1, "-    "),  'U' => (3, "..-  "),
      'V' => (4, "...- "), 'W' => (3, ".
      'Y' => (4, "-.
      '2' => (5, "..
      '5' => (5, "....."), '6' => (5, "-...."),  '7' => (5, "
      '8' => (5, "
      others => (1, "     ")); 

end Morse;