← run

go-01-unique

1.000
3/3 tests· basic
Challenge · difficulty 1/5
# Unique preserving order

Implement **`solution.go`** in `package challenge` exporting:

```go
func Unique(xs []int) []int
```

Return a new slice containing the elements of `xs` with duplicates removed, keeping each value at
the position of its **first occurrence**.

Rules:

- Preserve **first-occurrence order** — do not sort the result.
- Each distinct value appears exactly once.
- Do **not** mutate the input slice.
- For an empty (or nil) input, return an **empty, non-nil** slice (length 0).

Examples:

```go
Unique([]int{3, 1, 3, 2, 1}) // => [3, 1, 2]
Unique([]int{1, 2, 3})       // => [1, 2, 3]
Unique([]int{5, 5, 5})       // => [5]
Unique([]int{})              // => [] (non-nil, length 0)
```
tests/solution_test.go
package challenge

import (
	"reflect"
	"testing"
)

func TestUnique(t *testing.T) {
	cases := []struct {
		name string
		in   []int
		want []int
	}{
		{"removes duplicates preserving order", []int{3, 1, 3, 2, 1}, []int{3, 1, 2}},
		{"already unique unchanged", []int{1, 2, 3}, []int{1, 2, 3}},
		{"all same collapses to one", []int{5, 5, 5}, []int{5}},
		{"empty returns empty", []int{}, []int{}},
		{"single element", []int{42}, []int{42}},
		{"negatives and zero", []int{0, -1, 0, -1, 2}, []int{0, -1, 2}},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			got := Unique(tc.in)
			if !reflect.DeepEqual(got, tc.want) {
				t.Errorf("Unique(%v) = %v, want %v", tc.in, got, tc.want)
			}
		})
	}
}

func TestUniqueReturnsNonNil(t *testing.T) {
	if Unique([]int{}) == nil {
		t.Error("Unique should return a non-nil slice for empty input")
	}
	if Unique(nil) == nil {
		t.Error("Unique should return a non-nil slice for nil input")
	}
}

func TestUniqueDoesNotMutateInput(t *testing.T) {
	in := []int{1, 1, 2}
	_ = Unique(in)
	if !reflect.DeepEqual(in, []int{1, 1, 2}) {
		t.Errorf("input was mutated: got %v", in)
	}
}
System prompt
You are an expert programmer. Solve the task exactly as specified. Output your solution as fenced code blocks using the required file name(s) and the exact function/type signatures requested. Prefer correctness; do not include prose outside code unless asked.
Proposed solution
```go
package challenge

func Unique(xs []int) []int {
	if len(xs) == 0 {
		return []int{}
	}

	seen := make(map[int]struct{})
	result := make([]int, 0, len(xs))

	for _, x := range xs {
		if _, exists := seen[x]; !exists {
			seen[x] = struct{}{}
			result = append(result, x)
		}
	}

	return result
}
```

Test output (stdout)

e":"2026-07-02T00:04:33.036483601+02:00","Action":"output","Package":"challenge","Test":"TestUnique/all_same_collapses_to_one","Output":"--- PASS: TestUnique/all_same_collapses_to_one (0.00s)\n"}
{"Time":"2026-07-02T00:04:33.036485041+02:00","Action":"pass","Package":"challenge","Test":"TestUnique/all_same_collapses_to_one","Elapsed":0}
{"Time":"2026-07-02T00:04:33.036486391+02:00","Action":"run","Package":"challenge","Test":"TestUnique/empty_returns_empty"}
{"Time":"2026-07-02T00:04:33.036487601+02:00","Action":"output","Package":"challenge","Test":"TestUnique/empty_returns_empty","Output":"=== RUN   TestUnique/empty_returns_empty\n"}
{"Time":"2026-07-02T00:04:33.036489341+02:00","Action":"output","Package":"challenge","Test":"TestUnique/empty_returns_empty","Output":"--- PASS: TestUnique/empty_returns_empty (0.00s)\n"}
{"Time":"2026-07-02T00:04:33.036491031+02:00","Action":"pass","Package":"challenge","Test":"TestUnique/empty_returns_empty","Elapsed":0}
{"Time":"2026-07-02T00:04:33.036492591+02:00","Action":"run","Package":"challenge","Test":"TestUnique/single_element"}
{"Time":"2026-07-02T00:04:33.036493651+02:00","Action":"output","Package":"challenge","Test":"TestUnique/single_element","Output":"=== RUN   TestUnique/single_element\n"}
{"Time":"2026-07-02T00:04:33.036496861+02:00","Action":"output","Package":"challenge","Test":"TestUnique/single_element","Output":"--- PASS: TestUnique/single_element (0.00s)\n"}
{"Time":"2026-07-02T00:04:33.036498151+02:00","Action":"pass","Package":"challenge","Test":"TestUnique/single_element","Elapsed":0}
{"Time":"2026-07-02T00:04:33.036499411+02:00","Action":"run","Package":"challenge","Test":"TestUnique/negatives_and_zero"}
{"Time":"2026-07-02T00:04:33.036500771+02:00","Action":"output","Package":"challenge","Test":"TestUnique/negatives_and_zero","Output":"=== RUN   TestUnique/negatives_and_zero\n"}
{"Time":"2026-07-02T00:04:33.036502501+02:00","Action":"output","Package":"challenge","Test":"TestUnique/negatives_and_zero","Output":"--- PASS: TestUnique/negatives_and_zero (0.00s)\n"}
{"Time":"2026-07-02T00:04:33.036503891+02:00","Action":"pass","Package":"challenge","Test":"TestUnique/negatives_and_zero","Elapsed":0}
{"Time":"2026-07-02T00:04:33.036505481+02:00","Action":"output","Package":"challenge","Test":"TestUnique","Output":"--- PASS: TestUnique (0.00s)\n"}
{"Time":"2026-07-02T00:04:33.036506921+02:00","Action":"pass","Package":"challenge","Test":"TestUnique","Elapsed":0}
{"Time":"2026-07-02T00:04:33.036509581+02:00","Action":"run","Package":"challenge","Test":"TestUniqueReturnsNonNil"}
{"Time":"2026-07-02T00:04:33.036510881+02:00","Action":"output","Package":"challenge","Test":"TestUniqueReturnsNonNil","Output":"=== RUN   TestUniqueReturnsNonNil\n"}
{"Time":"2026-07-02T00:04:33.036512801+02:00","Action":"output","Package":"challenge","Test":"TestUniqueReturnsNonNil","Output":"--- PASS: TestUniqueReturnsNonNil (0.00s)\n"}
{"Time":"2026-07-02T00:04:33.036514351+02:00","Action":"pass","Package":"challenge","Test":"TestUniqueReturnsNonNil","Elapsed":0}
{"Time":"2026-07-02T00:04:33.036516981+02:00","Action":"run","Package":"challenge","Test":"TestUniqueDoesNotMutateInput"}
{"Time":"2026-07-02T00:04:33.036518211+02:00","Action":"output","Package":"challenge","Test":"TestUniqueDoesNotMutateInput","Output":"=== RUN   TestUniqueDoesNotMutateInput\n"}
{"Time":"2026-07-02T00:04:33.036520601+02:00","Action":"output","Package":"challenge","Test":"TestUniqueDoesNotMutateInput","Output":"--- PASS: TestUniqueDoesNotMutateInput (0.00s)\n"}
{"Time":"2026-07-02T00:04:33.036521941+02:00","Action":"pass","Package":"challenge","Test":"TestUniqueDoesNotMutateInput","Elapsed":0}
{"Time":"2026-07-02T00:04:33.036523411+02:00","Action":"output","Package":"challenge","Output":"PASS\n"}
{"Time":"2026-07-02T00:04:33.036708734+02:00","Action":"output","Package":"challenge","Output":"ok  \tchallenge\t0.001s\n"}
{"Time":"2026-07-02T00:04:33.036722444+02:00","Action":"pass","Package":"challenge","Elapsed":0.001}