Skip to content

Commit

Permalink
day 6 solution. xor linked list
Browse files Browse the repository at this point in the history
  • Loading branch information
vaskoz committed Aug 28, 2018
1 parent cefb591 commit f5f6b4f
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 0 deletions.
28 changes: 28 additions & 0 deletions day6/problem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package day6

import (
"unsafe"
)

// XorList is an xor doubly linked list
type XorList struct {
val interface{}
both uintptr // prev xor next
}

// New returns a pointer to an XorList
func New(val interface{}) *XorList {
return &XorList{val: val, both: 0}
}

// Add adds a new value
func (xl *XorList) Add(val interface{}) {
prev := uintptr(0)
this := unsafe.Pointer(xl)
for prev^xl.both != 0 {
prev, this = uintptr(this), unsafe.Pointer(prev^xl.both)
xl = (*XorList)(this)
}
nxl := &XorList{val: val, both: uintptr(this)}
xl.both = prev ^ uintptr(unsafe.Pointer(nxl))
}
53 changes: 53 additions & 0 deletions day6/problem_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package day6

import (
"reflect"
"testing"
"unsafe"
)

var testcases = []struct {
data []interface{}
}{
{[]interface{}{6, 10, 30, 40, 100, 101, 102}},
{[]interface{}{102, 101, 33, 44, 101, 25, 29, 50, 76}},
{[]interface{}{102, 101, 100, 99, 88, 77, 66, 55, 44, 33, 22, 11}},
}

func TestXorList(t *testing.T) {
for _, tc := range testcases {
xl := New(tc.data[0])
for i := 1; i < len(tc.data); i++ {
xl.Add(tc.data[i])
}
if result := forwardToSlice(xl); !reflect.DeepEqual(result, []interface{}(tc.data)) {
t.Errorf("Expected %v but got %v", tc.data, result)
}
}
}

func BenchmarkXorList(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tc := range testcases {
xl := New(tc.data[0])
for i := 1; i < len(tc.data); i++ {
xl.Add(tc.data[i])
}
}
}
}

// forwardToSlice is a testing utility to iterate through this list and construct a slice.
// it's easier to assert on.
func forwardToSlice(xl *XorList) []interface{} {
var result []interface{}
prev := uintptr(0)
this := unsafe.Pointer(xl)
result = append(result, xl.val)
for prev^xl.both != 0 {
prev, this = uintptr(this), unsafe.Pointer(prev^xl.both)
xl = (*XorList)(this)
result = append(result, xl.val)
}
return result
}

0 comments on commit f5f6b4f

Please sign in to comment.