Kraštiniai atvejai — čia ji ir lūžta
Sukurk search_test.go (žr. dešinėje). Šitą testą rašom mes; tavo darbas —
kad LowerBound jį praeitų.
Laimingas atvejis — „įrašas kažkur viduryje" — yra lengvas. Visos toliau išvardytos vietos yra ten, kur ranka rašyta dvejetainė paieška iš tikrųjų lūžta.
Dešimt kraštinių atvejų
$ go test -run TestLowerBoundBoundaries -v .
=== RUN TestLowerBoundBoundaries/exact_match,_first
=== RUN TestLowerBoundBoundaries/exact_match,_middle
=== RUN TestLowerBoundBoundaries/exact_match,_last
=== RUN TestLowerBoundBoundaries/between_two_items
=== RUN TestLowerBoundBoundaries/before_everything
=== RUN TestLowerBoundBoundaries/AFTER_everything
=== RUN TestLowerBoundBoundaries/empty_slice
=== RUN TestLowerBoundBoundaries/single_item,_before
=== RUN TestLowerBoundBoundaries/single_item,_exact
=== RUN TestLowerBoundBoundaries/single_item,_after
--- PASS: TestLowerBoundBoundaries (0.00s)
Trys iš jų verti atskiro žodžio.
„AFTER everything" grąžina 4, kai bibliotekoje 4 įrašai. Indeksas, kurio
nėra. Būtent todėl hi pradedamas nuo len(items), o ne nuo len(items)-1:
atsakymas „už galo" turi turėti kur tilpti. Pradėk nuo len-1 ir šis atvejis
tyliai grąžins paskutinį įrašą.
Tuščias slice grąžina 0 ir neišvis nepatenka į ciklą, nes lo < hi iškart
neteisinga. Nulinis atvejis pasitvarko pats — jei invariantas teisingas.
Vieno įrašo biblioteka tikrinama tris kartus, nes joje mid visada 0 ir
klaida su mid + 1 čia virsta amžinuoju ciklu.
Dublikatai: kurį iš trijų?
lib := sorted("a", "b", "b", "b", "c")
LowerBound(lib, "b") // → 1
Trys „b". Teisingas atsakymas — pirmasis, indeksas 1. Tai ir reiškia lower bound.
Jei tavo paieška grąžina 2 arba 3, ji atrodo teisinga ir praeis paviršutinišką patikrinimą. Bet kodas, kuris nuo rezultato eina pirmyn rinkdamas visus sutampančius įrašus, praleis dalį jų — ir klaida išlįs kur nors kitur, visiškai kitoje vietoje.
transit savo paieškos semantiką irgi testuoja, o ne prielaidauja.
Ir svarbiausias testas
$ go test -run TestUnsortedInputSilentlyLies -v .
search_test.go:93: unsorted input: linear says 0, binary says 2 —
binary is wrong, and silent
Nesurikiuotas įvedimas dvejetainei paieškai nėra klaida. Ji nepraneša nieko. Ji tiesiog grąžina neteisingą skaičių.
Surikiuota tvarka yra prielaida, o ne rekomendacija. Tiesinė paieška veikia visada; dvejetainė veikia tik tada, kai jos sąlyga išpildyta, ir pati to netikrina — patikrinimas kainuotų O(n) ir sunaikintų visą prasmę. Prielaidas saugo tavo programa, ne paieška.