summary refs log tree commit diff stats
path: root/go/hamming/hamming_test.go
blob: 82e8a8e3391c0dee8db89c0e22b19c328ee98c0f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package hamming

import "testing"

func TestHamming(t *testing.T) {
	for _, tc := range testCases {
		got, err := Distance(tc.s1, tc.s2)
		if tc.expectError {
			// check if err is of error type
			var _ error = err

			// we expect error
			if err == nil {
				t.Fatalf("Distance(%q, %q); expected error, got nil.",
					tc.s1, tc.s2)
			}
		} else {
			// we do not expect error
			if err != nil {
				t.Fatalf("Distance(%q, %q) returned unexpected error: %v",
					tc.s1, tc.s2, err)
			}
			if got != tc.want {
				t.Fatalf("Distance(%q, %q) = %d, want %d.",
					tc.s1, tc.s2, got, tc.want)
			}

		}
	}
}

func BenchmarkHamming(b *testing.B) {
	// bench combined time to run through all test cases
	for i := 0; i < b.N; i++ {
		for _, tc := range testCases {
			// ignoring errors and results because we're just timing function execution
			_, _ = Distance(tc.s1, tc.s2)
		}
	}
}
gle */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
# Primitives for screen control.
# Require Linux and a modern terminal.

== code

enable-screen-grid-mode:
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    #
    (flush Stdout)
    (flush Stderr)
    # switch to second screen buffer
    (write 1 Esc)
    (write 1 "[?1049h")
    #
    (clear-real-screen)
$enable-screen-grid-mode:end:
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

enable-screen-type-mode:
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # switch to first screen buffer
    (write 1 Esc)
    (write 1 "[?1049l")
$enable-screen-type-mode:end:
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

real-screen-size:  # -> nrows/eax: int, ncols/ecx: int
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    52/push-edx
    53/push-ebx
    56/push-esi
    57/push-edi
    #
    (_maybe-open-terminal)
    # var window-size-info/esi: (addr winsize)
    # winsize is a type from the Linux kernel. We don't care how large it is.
    81 5/subop/subtract %esp 0x40/imm32
    89/<- %esi 4/r32/esp
    # ioctl(*Terminal-file-descriptor, TIOCGWINSZ, window-size-info)
    89/<- %edx 6/r32/esi
    b9/copy-to-ecx 0x5413/imm32/TIOCGWINSZ
    8b/-> *Terminal-file-descriptor 3/r32/ebx
    e8/call syscall_ioctl/disp32
    # some bitworking to extract 2 16-bit shorts
    8b/-> *esi 0/r32/eax
    81 4/subop/and %eax 0xffff/imm32
    8b/-> *esi 1/r32/ecx
    c1/shift 5/subop/logical-right %ecx 0x10/imm8
$real-screen-size:end:
    # . reclaim locals
    81 0/subop/add %esp 0x40/imm32
    # . restore registers
    5f/pop-to-edi
    5e/pop-to-esi
    5b/pop-to-ebx
    5a/pop-to-edx
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

clear-real-screen:
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    #
    (write 1 Esc)
    (write 1 "[H")
    (write 1 Esc)
    (write 1 "[2J")
$clear-real-screen:end:
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

# row and col count from the top-left as (1, 1)
move-cursor-on-real-screen:  # row: int, column: int
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    51/push-ecx
    # var buf/ecx: (stream byte 32)
    81 5/subop/subtract %esp 0x20/imm32
    68/push 0x20/imm32/size
    68/push 0/imm32/read
    68/push 0/imm32/write
    89/<- %ecx 4/r32/esp
    # construct directive in buf
    (write %ecx Esc)
    (write %ecx "[")
    (write-int32-decimal %ecx *(ebp+8))
    (write %ecx ";")
    (write-int32-decimal %ecx *(ebp+0xc))
    (write %ecx "H")
    # flush
    (write-stream 2 %ecx)
$move-cursor-on-real-screen:end:
    # . reclaim locals
    81 0/subop/add %esp 0x2c/imm32
    # . restore registers
    59/pop-to-ecx
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

print-string-to-real-screen:  # s: (addr array byte)
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    #
    (write 1 *(ebp+8))
$print-string-to-real-screen:end:
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

print-stream-to-real-screen:  # s: (addr stream byte)
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    #
    (write-stream-data Stdout *(ebp+8))
    (flush Stdout)
$print-stream-to-real-screen:end:
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

# print a grapheme in utf-8 (only up to 4 bytes so far)
print-grapheme-to-real-screen:  # c: grapheme
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    50/push-eax
    # var curr/eax: byte = 0
    b8/copy-to-eax 0/imm32
    # curr = *(ebp+8)
    8a/byte-> *(ebp+8) 0/r32/al
    # if (curr == 0) return
    3d/compare-eax-and 0/imm32
    74/jump-if-= $print-grapheme-to-real-screen:end/disp8
    #
    (print-byte-to-real-screen %eax)
    # curr = *(ebp+9)
    8a/byte-> *(ebp+9) 0/r32/al
    # if (curr == 0) return
    3d/compare-eax-and 0/imm32
    74/jump-if-= $print-grapheme-to-real-screen:end/disp8
    #
    (print-byte-to-real-screen %eax)
    # curr = *(ebp+10)
    8a/byte-> *(ebp+0xa) 0/r32/al
    # if (curr == 0) return
    3d/compare-eax-and 0/imm32
    74/jump-if-= $print-grapheme-to-real-screen:end/disp8
    #
    (print-byte-to-real-screen %eax)
    # curr = *(ebp+11)
    8a/byte-> *(ebp+0xb) 0/r32/al
    # if (curr == 0) return
    3d/compare-eax-and 0/imm32
    74/jump-if-= $print-grapheme-to-real-screen:end/disp8
    #
    (print-byte-to-real-screen %eax)
$print-grapheme-to-real-screen:end:
    # . restore registers
    58/pop-to-eax
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

print-byte-to-real-screen:  # c: byte
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    51/push-ecx
    # var s/ecx: (addr array byte)
    ff 6/subop/push *(ebp+8)
    68/push 1/imm32/size
    89/<- %ecx 4/r32/esp
    (write 1 %ecx)
$print-byte-to-real-screen:end:
    # . reclaim locals
    81 0/subop/add %esp 8/imm32
    # . restore registers
    59/pop-to-ecx
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

print-int32-hex-to-real-screen:  # n: int
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    #
    (write-int32-hex-buffered Stdout *(ebp+8))
    (flush Stdout)
$print-int32-hex-to-real-screen:end:
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

reset-formatting-on-real-screen:
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    #
    (write 1 Esc)
    (write 1 "(B")
    (write 1 Esc)
    (write 1 "[m")
$reset-formatting-on-real-screen:end:
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

start-color-on-real-screen:  # fg: int, bg: int
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    51/push-ecx
    # var buf/ecx: (stream byte 32)
    81 5/subop/subtract %esp 0x20/imm32
    68/push 0x20/imm32/size
    68/push 0/imm32/read
    68/push 0/imm32/write
    89/<- %ecx 4/r32/esp
    # construct directive in buf
    # . set fg
    (write %ecx Esc)
    (write %ecx "[38;5;")
    (write-int32-decimal %ecx *(ebp+8))
    (write %ecx "m")
    # . set bg
    (write %ecx Esc)
    (write %ecx "[48;5;")
    (write-int32-decimal %ecx *(ebp+0xc))
    (write %ecx "m")
    # flush
    (write-stream 2 %ecx)
$start-color-on-real-screen:end:
    # . reclaim locals
    81 0/subop/add %esp 0x2c/imm32
    # . restore registers
    59/pop-to-ecx
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

start-bold-on-real-screen:
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    #
    (write 1 Esc)
    (write 1 "[1m")
$start-bold-on-real-screen:end:
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

start-underline-on-real-screen:
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    #
    (write 1 Esc)
    (write 1 "[4m")
$start-underline-on-real-screen:end:
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

start-reverse-video-on-real-screen:
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    #
    (write 1 Esc)
    (write 1 "[7m")
$start-reverse-video-on-real-screen:end:
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

# might require enabling blinking in your terminal program
start-blinking-on-real-screen:
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    #
    (write 1 Esc)
    (write 1 "[5m")
$start-blinking-on-real-screen:end:
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

hide-cursor-on-real-screen:
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    #
    (write 1 Esc)
    (write 1 "[?25l")
$hide-cursor-on-real-screen:end:
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

show-cursor-on-real-screen:
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    #
    (write 1 Esc)
    (write 1 "[?12l")
    (write 1 Esc)
    (write 1 "[?25h")
$show-cursor-on-real-screen:end:
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

# This is a low-level detail; I don't think everything should be a file.
#
# Open "/dev/tty" if necessary and cache its file descriptor in Terminal-file-descriptor
# where later primitives can use it.
_maybe-open-terminal:
    81 7/subop/compare *Terminal-file-descriptor -1/imm32
    75/jump-if-!= $_maybe-open-terminal:epilogue/disp8
    # . save registers
    50/push-eax
    51/push-ecx
    53/push-ebx
    # open("/dev/tty", O_RDWR)
    bb/copy-to-ebx Terminal-filename/imm32
    b9/copy-to-ecx 2/imm32/O_RDWR
    e8/call syscall_open/disp32
    89/<- *Terminal-file-descriptor 0/r32/eax
$_maybe-open-terminal:end:
    # . restore registers
    5b/pop-to-ebx
    59/pop-to-ecx
    58/pop-to-eax
$_maybe-open-terminal:epilogue:
    c3/return

== data

Terminal-file-descriptor:  # (addr int)
  -1/imm32

Esc:  # (addr array byte)
  # size
  1/imm32
  # data
  0x1b

Terminal-filename:  # (addr kernel-string)
  # "/dev/null"
  2f/slash 64/d 65/e 76/v 2f/slash 74/t 74/t 79/y 0/nul