small medium large xlarge

• I’m thinking of a number between 1 and 1000…

The most efficient way to find the number is to guess halfway between the low and high numbers of the range. If our guess is too big, then the answer lies between the bottom of the range and one less than our guess. If it is too small, then the answer lies between one more than our guess and the end of the range.

Code this up. Your API will be `guess(actual, range)`, where `range` is an Elixir range.

Your output should look similar to:

``````iex> Chop.guess(273, 1..1000)
Is it 500
Is it 250
Is it 375
Is it 312
Is it 281
Is it 265
Is it 273
273
``````

Hints:

• You may need to implement helper functions with an additional parameter (the currently guessed number).
• the `div(a,b)` function performs integer division
• guard clauses are your friends
• patterns can match the low and high parts of a range (`a..b=4..8`) === {::comment} defmodule Chop do def guess(actual, range = low..high) do guess = div(low+high, 2) IO.puts “Is it #{guess}” guess(actual, guess, range) end

def guess(actual, actual, _), do: actual def guess(actual, guess, _low..high) when guess < actual, do: guess(actual, guess+1..high) def guess(actual, guess, low.._high) when guess > actual, do: guess(actual, low..guess-1) end {:/comment}

</yourturn>

A Possible Solution</summary>

```defmodule Chop do
def guess(actual, range = low..high) do
guess = div(low+high, 2)
IO.puts "Is it #{guess}?"
_guess(actual, guess, range)
end

defp _guess(actual, actual, _),
do: IO.puts "Yes, it's #{actual}"

defp _guess(actual, guess,  _low..high)
when guess < actual,
do: guess(actual, guess+1..high)

defp _guess(actual, guess,  low.._high)
when guess > actual,
do: guess(actual, low..guess-1)
end

Chop.guess(273, 1..1000)
```

</details>

My solution:

``````defmodule Chop do
def guess(actual, range) do
n = next_guess(range)
check_guess(actual, range, n)
end

defp next_guess(low..high) do
difference = high - low
guess = div(difference, 2) + low

IO.puts "Is it #{guess}"

guess
end

defp check_guess(actual, _, current_guess) when current_guess == actual do
actual
end

defp check_guess(actual, low.._, current_guess) when current_guess > actual do
high = current_guess - 1
n = next_guess(low..high)
check_guess(actual, low..high, n)
end

defp check_guess(actual, _..high, current_guess) when current_guess < actual do
low = current_guess + 1
n = next_guess(low..high)
check_guess(actual, low..high, n)
end
end ---
``````

P.S. What mark up do I use to make a hidden thing Dave like your “A Possible Solution”? It’s not standard Markdown, so it must be something specific to this forum.

I use details/summary tags

I can’t figure out how to hide a code block with details/summary tags. Elixir 0.10.1

``````defmodule Chop do
def guess(actual, low..high)
when actual == div(low+high, 2) do
IO.puts "Is it #{actual}?"
IO.puts "Yes, it's #{actual}."
end

def guess(actual, low..high)
when actual < div(low+high, 2) do
IO.puts "Is it #{div(low+high, 2)}?"
guess(actual, low..div(low+high, 2))
end

def guess(actual, low..high)
when actual > div(low+high, 2) do
IO.puts "Is it #{div(low+high, 2)}?"
guess(actual, div(low+high, 2)..high)
end
end
``````

Hi Dave, your solution uses defp which is described later in chapter 7. I figured it out only looking the solution into this forum.

The syntax of defining a function that calls itself is also described later in chapter 7.

I’m still on chapter 6, but when I looked at your proposed solution I was stunned with the matching of parameters on the right hand of the = sign (range = low..high), it’s amazing but it only works on parameter definition and I didn’t see any explanation on that so far. Granted, it isn’t necessary to answer the Chop exercise, but I would expect such explanation under “Function Calls and Pattern Matching” that starts on page 45.

As a side note, so far I’m enjoying the book very much, thanks a bunch.

My solution:

``````defmodule Chop do
def guess(x, a..b) when x == div(a+b, 2) do
IO.puts "Is it #{x}"
IO.puts "#{x}"
end
def guess(x, a..b) when x < div(a+b, 2) do
n = div(a+b, 2)
IO.puts "Is it #{n}"
guess(x, a..n)
end
def guess(x, a..b) when x > div(a+b, 2) do
n = div(a+b, 2)
IO.puts "Is it #{n}"
guess(x, n..b)
end
end
``````

It’s very similar to Nathan J Schunemann solution

My solution is virtually identical with Luke’s answer, but I didn’t use `defp`. Not sure if that’s important, but the program compiled just fine (0.12.5).

I tried to code a similar solution in Kotlin and ended up with this:

``````tailRecursive
fun guess(answer: Int, range: Range<Int>, candidate: Int = (range.end - range.start) / 2 + range.start): Int =
when {
else                -> throw IllegalArgumentException("Computational error occurred; check the math please.")
}
``````

I like this solution a lot and attempted to code this solution in Elixir:

``````defmodule Chop do
def guess(answer, from..to, candidate \\ div(to - from, 2) + from) when candidate == answer do
end

def guess(answer, from..to, candidate \\ div(to - from, 2) + from) when candidate > answer do
end

def guess(answer, from..to, candidate \\ div(to - from, 2) + from) when candidate < answer do
end

end
end
``````

The first thing that struck me is, “There has to be an easier way” than defining four function and separating them with almost nothing but a different operator in the `when` clause. Secondly, the code fails with the error message:

``````** (CaseClauseError) no case clause matching: nil
(elixir) src/elixir_scope.erl:22: :elixir_scope.translate_var/4
(elixir) src/elixir_translator.erl:302: :elixir_translator.translate_arg/3
(stdlib) lists.erl:1339: :lists.mapfoldl/3
(elixir) src/elixir_translator.erl:209: :elixir_translator.translate/2
(elixir) src/elixir_translator.erl:302: :elixir_translator.translate_arg/3
(stdlib) lists.erl:1339: :lists.mapfoldl/3
(elixir) src/elixir_translator.erl:209: :elixir_translator.translate/2
(elixir) src/elixir_translator.erl:302: :elixir_translator.translate_arg/3
``````

I can’t help uploading my solution for all to see, as - to be honest - I’m chuffed that it worked. :-) I’ve added a few additional messages on output to help show what’s going on:

``````defmodule Chop do

def guess(target, x..y) do
midpoint = halfway(x, y)
match(target, x, y, midpoint)
end

defp halfway(x, y), do: div(y-x, 2) + x

defp match(target, _x, _y, target), do: target

defp match(target, x, _y, midpoint) when target < midpoint do
IO.puts "Is it #{midpoint}?\tNo, lower."
guess(target, x..midpoint)
end

defp match(target, _x, y, midpoint) do # in the upper range.
IO.puts "Is it #{midpoint}?\tNo, higher."
guess(target, midpoint..y)
end

end
``````

When you run my code, here’s what you see:

``````iex(1)> Chop.guess(273, 1..1000)
Is it 500?      No, lower.
Is it 250?      No, higher.
Is it 375?      No, lower.
Is it 312?      No, lower.
Is it 281?      No, lower.
Is it 265?      No, higher.
273
``````

My solution based in the Dave T. solution.

``````defmodule Game do
def guess(resp, low..high)
when resp < low or resp > high do
IO.puts "[error] Use a value between #{low} and #{high}."
end

def guess(resp, low..high) do
guess = div(low+high, 2)
IO.puts "Is it #{guess}"
_find(resp, guess, low, high)
end

defp _find(resp, resp, _, _), do: IO.puts "-> #{resp}"

defp _find(resp, guess, low, _)
when guess > resp do
guess(resp, low..guess - 1)
end

defp _find(resp, guess, _, high)
when guess < resp do
guess(resp, guess + 1..high)
end
end

Game.guess(20, 0..100)
Game.guess(20, 50..100)
Game.guess(50, 50..100)
Game.guess(100, 50..100)
``````

My solution is to narrow down the range of possibilities with every guess and finally converge on the actual value.

```defmodule Chop do
def guess(actual, actual.._), do: actual
def guess(actual, _..actual), do: actual
def guess(actual, low..high) do
midpoint = low + div(high - low, 2)
IO.puts "Is it #{midpoint}?"
if actual < midpoint do
guess actual, low..midpoint
else
guess actual, midpoint..high
end
end
end
```

This is my solution:

``````defmodule Chop do
def guess(actual, low..high) when actual > low and actual< high do
_guess(actual, low..high, div(low + high, 2))
end

defp _guess(actual, _, curr) when curr == actual do
IO.puts "Is it #{curr}"
IO.puts curr
end

defp _guess(actual, low..high, curr) when curr < actual do
IO.puts "Is it #{curr}"
_guess actual, curr..high, div(curr + high, 2)
end

defp _guess(actual, low..high, curr) when curr > actual do
IO.puts "Is it #{curr}"
_guess actual, low..curr, div(low + curr, 2)
end
end
``````
``````defmodule Chop do
def guess(num, low..high) when num > div(high + low, 2) do
IO.puts "Is it #{div(high + low, 2)}"
guess(num, div(high + low, 2)..high)
end
def guess(num, low..high) when num < div(high + low, 2) do
IO.puts "Is it #{div(high + low, 2)}"
guess(num, low..div(high + low, 2))
end
def guess(num, low..high) do
IO.puts num
end
end

Chop.guess(273, 1..1000)
``````

And another one

``````
defmodule Guess do

def is(number, guess, _a..b) when number > guess do
it(number, (guess+1)..b)
end

def is(number, guess, a.._b) when number < guess do
it(number, a..(guess-1))
end

def is(number, guess, _a.._b) when number == guess do
IO.puts guess
end

def it(number, a..b = range) when a <= number and b >= number do
guess = div(b-a,2) + a
IO.puts "Is it #{guess}?"
is(number, guess, range)
end
end

``````
```defmodule Chop do
def guess(num, range) do
guess(num, range, 0)
end

defp guess(num, range, guess) when num == guess do
IO.puts "It is #{guess}!"
end

defp guess(num, range, guess) when guess > num do
min.._ = range
new_range = min..guess
next_guess = mid(new_range)
IO.puts "Is it #{next_guess}?"
guess(num, new_range, next_guess)
end

defp guess(num, range, guess) when guess < num do
_..max = range
new_range = guess..max
next_guess = mid(new_range)
IO.puts "Is it #{next_guess}?"
guess(num, new_range, next_guess)
end

defp mid(range) do
min..max = range
mid = div(min + max, 2)
mid
end
end

```
``````defmodule Chop do
def guess(actual, _, actual), do: IO.puts "Yes, it's #{actual}"
def guess(actual, low.._, guess) when guess > actual, do: guess(actual, low..guess-1)
def guess(actual, _..high, guess) when guess < actual, do: guess(actual, guess+1..high)
def guess(actual, low..high) do
guess = div(low+high, 2)
IO.puts "Is it #{guess}?"
guess(actual, low..high, guess)
end
end
``````
``````defmodule Chop do
def guess actual, range = low..high do
current = div(high+low, 2)
IO.puts "Is it #{current}"
isit(current, actual, range)
end

def isit(current, actual, low.._high )
when current > actual do
guess(actual, low..current-1)
end

def isit(current, actual, _low..high)
when current < actual do
guess(actual, current+1..high)
end

# borrow this idea from Mr. Dave .. this is so clever :)
def isit(actual, actual, _) do
IO.puts "Yes it is #{actual}"
end

end

Chop.guess 273, 1..1000
``````
``````defmodule Chop do
def evaluate(actual, guess, _) when guess == actual do
IO.puts "Is it #{guess}"
guess
end

def evaluate(actual, guess, a..b) when guess < actual do
IO.puts "Is it #{guess}"
new_range = guess..b
new_guess = mid(new_range)
evaluate(actual, new_guess, new_range)
end

def evaluate(actual, guess, a..b) when guess > actual do
IO.puts "Is it #{guess}"
new_range = a..guess
new_guess = mid(new_range)
evaluate(actual, new_guess, a..guess)
end

def guess(actual, a..b) do
first_guess = mid(a..b)
evaluate(actual, first_guess, a..b)
end

def mid(a..b) do
div(a+b,2)
end
end
``````

I think I might have messed up by using cond do since no one else did. It’s so concise though…

``````defmodule Chop do
def guess(actual, h..t) do
g = div((t - h), 2) + h
IO.puts "Is it #{g}"
cond do
g == actual -> actual
g < actual -> guess(actual, g + 1..t)
g > actual -> guess(actual, h..g - 1)
end
end
end
``````
``````iex> Chop.guess 783, 1..1000
Is it 500
Is it 750
Is it 875
Is it 812
Is it 781
Is it 796
Is it 788
Is it 784
Is it 782
Is it 783
783
``````

My solution is not that elegant.. but still works but definitely I should swtich to Nathan J Schunemann solution

``````defmodule Chop do
def guess(x, min..max) do
guessing(x, min, max)
end

def guessing(x, min, max) when x < div(max+min, 2) do
IO.puts "Is it #{div(max + min, 2)}"
guessing(x, min, div(max + min, 2))
end

def guessing(x, min, max) when x > div(max+min, 2) do
IO.puts "Is it #{div(max + min, 2)}"
guessing(x, div(max + min, 2), max)
end

def guessing(x, min, max) when x == div(max+min, 2) do
IO.puts "Is it #{div(max + min, 2)}"
IO.puts "#{div(max + min, 2)}"
end
end
``````

My first version was close to what Dave has proposed.

``````defmodule Chop do
def guess(m, a..b) do
check_guess(div(a+b,2), m, a..b)
end
def check_guess(g, m, _a.._b) when m == g do
IO.puts "It is #{g}"
end
def check_guess(g, m, _a..b) when m > g do
IO.puts "Is it #{g}?"
guess(m, g..b)
end
def check_guess(g, m, a.._b) when m < g do
IO.puts "Is it #{g}?"
guess(m, a..g)
end
end

Chop.guess(273, 1..1000)
``````

I came up with about the same answer as Srikanth: I’m really enjoying Elixir so far. An ex-coworker and I have plans to build a few websites using Aurelia and Elixir so this is my way of getting prepared for the task.

``````defmodule Chop do
def guess(x, a..b), do: guess(x, a..b, div((a + b), 2))
def guess(x, a..b, c) when c > x do
IO.puts "Is it #{c} ... no to high"
guess(x, a..(c-1))
end
def guess(x, a..b, c) when c < x do
IO.puts "Is it #{c} ... no to low"
guess(x, (c+1)..b)
end
def guess(x, a..b, c) when c == x do
IO.puts "Is it #{c} ... Why yes it is!!"j
end
end

``````

This is my version, elixir so surprising me :)

``````defmodule Chop do
def guess(n, range) do
determine n, middle(range), range
end

def determine(current, guessed, range) when current < guessed do
IO.puts "It is #{guessed}"
first..last = range
determine current, middle(first..guessed), first..guessed
end

def determine(current, guessed, range) when current > guessed do
IO.puts "It is #{guessed}"
first..last = range
determine current, middle(guessed..last), guessed..last
end

def determine(current, guessed, _) when current == guessed do
IO.puts current
end

defp middle(range) do
first..last = range
div((first + last), 2)
end
end

``````

My naive version:

``````defmodule Chop do
end

end

IO.puts "It's lower than #{number}, but higher than #{low}"
guess(answer, number - div(number - low, 2), low, number)
end

IO.puts "It's higher than #{number}, but lower than #{high}"
guess(answer, number + div(high - number, 2), number, high)
end
end
``````
```defmodule Chop do
def guess(actual, low..high) do
n = div(low+high, 2)
IO.puts "Is it #{n}?"
cond do
actual > n  -> guess(actual, n..high)
actual < n  -> guess(actual, low..n)
true        -> IO.puts "It's #{actual}!"
end
end
end

Chop.guess 273, 1..1000
```

I needed to have a quick look at the recommended solution to get a general gist of the logic - but I just about managed a slightly less efficient solution on (almost) my own. It’s the maths/logic I struggle with more than the language!

After bringing it in line I ended up building in some more protection, as you say;

``````def guess(actual, range = low..high) when is_number(actual) and is_map(range) do
if(actual >= low and actual <= high) do
guess = div(low + high, 2)
IO.puts "Is it… #{guess}?"
guess_attempt(actual, guess, range)
else
IO.puts "Nice try, Neo."
end
end
``````

This allows for negative numbers, but NOT Chop.guess(-37, 5..27).

It’s easier to check for valid calls with a “when actual in low..high” clause on the main guess function. That rejects any cases of type mismatches as well as actual values outside the supplied range.

My Solution:

``````defmodule Chop do
def guess(n, low..high)  do
match(n, low..high, midpoint(low..high))
end

def match(n, _, mid) when n == mid do
IO.puts "Is it #{n}"
IO.puts n
end

def match(n, low.._, mid) when n < mid do
IO.puts "Is it #{mid}"
match(n, low..mid, midpoint(low..mid))
end

def match(n, _..high, mid) when n > mid do
IO.puts "Is it #{mid}"
match(n, mid..high, midpoint(mid..high))
end

def midpoint(low..high), do: div((high+low),2)
end
``````
``````
defmodule Chop do

def guess(actual,_..actual) do
IO.puts "#{actual}"
end
def guess(actual,min..max) when div(max+min,2) >= actual do
max = div(max+min,2)
IO.puts "Is it #{max}"
guess(actual,min..max)
end
def guess(actual,min..max) when div(max+min,2) < actual do
min = div(max+min,2)
IO.puts "Is it #{min}"
guess(actual,min..max)
end
end
``````

I found this the nicest excersise till now (I’m in chapter 6). I had to use a combination of the knowledge gained in previous chapters. Working with the tutorial for 1.2, only using the language learned till the exercise:

``````defmodule Chop do:
def guess(prevguess \\ 0, nr, range)

def guess(prevguess, nr, first..last) when nr === last do
IO.puts "It is #{last}"
end

def guess(prevguess, nr, first..last) when nr in first..last do
g = last - div(last - first, 2) - 1
IO.puts "Is it#{g}?"
guess(last, nr, first..g)
end

def guess(prevguess, nr, first..last) when nr > last do
g = prevguess - div(last - first, 2) - 1
IO.puts "Is it#{g}?"
guess(prevguess, nr, (last + 1)..g)
end
end
``````

Here’s mine. The “Is it…?” is only printed once. I’m not sure how appropriately “functional” my solution is; it would work fine in Ruby with some word-to-word translations.

``````defmodule Chop do
def continue(number, middle, _..b) when number > middle, do: guess(number, middle..b)

def continue(number, middle, a.._) when number < middle, do: guess(number, a..middle)

def continue(number, middle, _) when number == middle, do: IO.puts number

def guess(number, a..b) do
middle = div(a+b, 2)
IO.puts "Is it #{middle}"

continue(number, middle, a..b)
end
end
``````

Here is my solution. I’m adding it because I added a guard clause to the main `guess/2` method to validate that actual is in the range. this took a while to figure out as you can’t just say `actual in range` you must make the range explicit using low..high.

```defmodule Chop do
def guess(actual, low..high) when actual in low..high do
candidate = div(low + high, 2)
IO.puts "Is it #{candidate}"
_guess(actual, candidate, low..high)
end

def _guess(actual, candidate, _low..high) when candidate < actual do
new_low = candidate + 1
guess(actual, new_low..high)
end

def _guess(actual, candidate, low.._high) when candidate > actual do
new_high = candidate - 1
guess(actual, low..new_high)
end

def _guess(_actual, candidate, _low.._high), do: candidate
end
```

My solution:

```defmodule Chop do
def guess(initial, a..b) do
guessing(initial, a, b)
end

def guess(initial, _, actual) when initial == actual do
actual
end

def guess(initial, a.._b, actual) when initial < actual do
guessing(initial, a, actual-1)
end

def guess(initial, _a..b, actual) when initial > actual do
guessing(initial, actual+1, b)
end

defp guessing(initial, a, b) do
actual = div(a+b,2)
IO.puts "is it #{actual} ?"
guess(initial, a..b, actual)
end
end
```
``````defmodule Chop do
def guess(actual, lower..upper) do
half = div((upper + lower), 2)
IO.puts "Is it #{half}"
cond do
actual < half  -> guess(actual, lower..half)
actual > half  -> guess(actual, half..upper)
actual == half -> actual
end
end
end
``````

If we don’t use conditional statements:

``````defmodule BinarySearch do

def guess(n, n..n), do: IO.puts n # Base Case: n could be matched.

def guess(n, low..high) when n > high or n < low, do: nil # Base Case: n is outside of the range.

def guess(n, low..high) do # Recursive Case: Find middle and recursively call with two subranges.
middle = div(high - low, 2) + low
IO.puts "Is it #{middle}?"
guess(n, low..middle) || guess(n, middle+1..high)
end

end

``````

My solution

``````defmodule Chop do
def guess(actual, range) do
first..last = range
center = div (first + last), 2
IO.puts "Is it #{center}"
cond do
actual == last -> IO.puts actual
actual == center -> IO.puts actual
actual < center -> last = center
guess(actual, first..last)
actual > center -> first = center
guess(actual, first..last)
end
end
end
``````

Here’s my solution. It’s similar to Dave Thomas’ solution and so many others already here. The main diference is to check if the range is the correct order and revert it if not.

``````defmodule Chop do
def guess(actual, _, actual) do
actual
end

def guess(actual, _..max, gvalue) when actual > gvalue do
guess(actual, gvalue..max)
end

def guess(actual, min.._, gvalue) when actual < gvalue do
guess(actual, min..gvalue)
end

def guess(actual, min..max) when max >= min and actual in min..max do
gvalue = div(max - min,2) + min
IO.puts "Is it #{gvalue}"
guess(actual, min..max, gvalue)
end

def guess(actual, min..max) when min > max and actual in min..max do
guess(actual, max..min)
end
end
``````

Solution with ugly repetition

How can this be refactored to get rid of repeated div(low + high, 2)?

``````defmodule Chop do
def guess(actual, low..high) when (actual == low) or (actual == high), do: (
IO.puts "got it! - #{actual}")

def guess(actual, low..high) when actual >= div(low + high, 2), do: (
IO.puts "#{actual} - #{low} - #{high}"
guess(actual, div(low + high,2)..high))

def guess(actual, low..high) when actual <= div(low + high, 2), do: (
IO.puts "#{actual} - #{low} - #{high}"
guess(actual, low..div(low + high,2)))
end

``````
``````defmodule Chop do

def guess(actual, a..b) do
guess(actual, div(a+b,2), a..b)
end

def guess(actual, guess, actual.._) do
IO.puts "Funny... #{actual}"
end

def guess(actual, guess, _..actual) do
IO.puts "Funny... #{actual}"
end

def guess(actual, actual, a..b) do
IO.puts "It's #{actual}!"
end

def guess(actual, guess, a..b) when actual < guess do
IO.puts "It's #{guess}!"
guess(actual, a..guess)
end

def guess(actual, guess, a..b) when actual > guess do
IO.puts "It's #{guess}!"
guess(actual, guess..b)
end

end
``````

probably needs some cleaning up, but I’m not sure how to do that yet ;D

My Solution:

``````defmodule Chop do
def guess(actual, min..max) when actual == div(max + min, 2) do
IO.puts("No, it is #{actual}")
end

def guess(actual, min..max) when actual > div(max + min, 2) do
IO.puts("Is it #{div(max + min, 2)}?")
guess(actual, (div(max + min, 2)..max))
end

def guess(actual, min..max) when actual < (min + div(max - min, 2)) do
IO.puts("Is it #{div(max + min, 2)}?")
guess(actual, min..div(max + min, 2))
end
end
``````

The hints were actually useful. It took some time for me to come up with this version of solution, but it was worth solving it.

``````defmodule Chop do

def guess(actual, a..b) when actual == div(a+b,2) do
IO.puts div(a+b,2)
end

def guess(actual, a..b) when actual < div(a+b,2) do
guess = div(a+b,2)
IO.puts "Is it #{guess}?"
guess(actual, a..guess-1)
end

def guess(actual, a..b) when actual > div(a+b,2) do
guess = div(a+b,2)
IO.puts "Is it #{guess}?"
guess(actual, guess+1..b)
end

end
``````

My initial naive solution :-/

```defmodule Chop do
def guess(n, low..high) do
guess = div(low + high, 2)

if n == low || n == high do
n
else
IO.puts("Is it #{guess}?")

if n <= guess do
guess(n, low..guess)
else
guess(n, guess..high)
end
end
end
end
```

After a quick peek, I could arrive at almost the same solution, except I added a guard on the public function to avoid guessing out of bound numbers.

```def guess(actual, range = low..high) when actual in low..high do
```

Looks like I cannot use `when actual in range` as a guard.

Love the beauty pattern-matching & `guard`ed functions have brought to the solution!

``````defmodule Chop do
def guess(actual,_..b) when actual>b, do: IO.puts "You naughty hacker, your number is out of range!"
def guess(actual,a.._) when actual<a, do: IO.puts "You naughty hacker, your number is out of range!"
def guess(actual,a..b) when div(a+b,2)>actual do
IO.puts "Is it #{div(a+b,2)}?"
guess(actual,a..div(a+b,2))
end
def guess(actual,a..b) when div(a+b,2)<actual do
IO.puts "Is it #{div(a+b,2)}?"
guess(actual,div(a+b,2)+1..b)
end
def guess(_,a..b), do: IO.puts "It is #{div(a+b,2)}"
end
``````
``````def guess(n, lower..upper) do
_guess(n, _next_guess(lower, upper), lower..upper)
end

def _guess(actual, current, _lower.._upper) when actual == current, do: actual
def _guess(actual, current, _lower..upper) when actual > current do
_guess_log(current)
_guess(actual, _next_guess(current, upper), current..upper)
end
def _guess(actual, current, lower.._upper) when actual < current do
_guess_log(current)
_guess(actual, _next_guess(lower, current), lower..current)
end

def _next_guess(lower, upper), do: div(lower+upper, 2)
def _guess_log(n), do: IO.puts "Is it #{n}?"
``````

My solution without private functions …

```defmodule Chop do
def guess(actual, actual.._) do
IO.puts("Yes, it's #{actual}.")
end

def guess(actual, low..high) when actual < div(high+low,2) do
IO.puts("Is it #{div(high+low,2)}?")
guess(actual, low..div(high+low,2))
end

def guess(actual, low..high)do
IO.puts("Is it #{div(high+low,2)}?")
guess(actual, div(high+low,2)..high)
end

end
```

Looking at Dave’s solution, made me rethink the problem…

I was confused before because I did not understand the low and high problem and run into infinite loops. Here’s my final code:

``````defmodule Chop do
def guess(actual, range = low..high) do
attempt = div(low+high, 2)
IO.puts "Is it #{attempt}"
check_guess(actual, attempt, range)
end

def check_guess(actual, attempt, _) when attempt == actual do
IO.puts "You got it! It's #{actual}"
end
def check_guess(actual, attempt, low.._high) when attempt > actual do
guess(actual, low..attempt - 1)
end
def check_guess(actual, attempt, _low..high) when attempt < actual do
guess(actual, attempt + 1..high)
end
end

Chop.guess(273, 1..1000)
``````

I love the code `range = low..high`, it saves me another line to explicitly say `low..high = range`. I did not think it first because for me `=` is still assignment.

``````defmodule Chop do
def guess(actual, low..high) when actual > div(low+high,2) do
IO.puts "Is it: #{n = div(low+high,2)}"
guess(actual, n+1..high)
end

def guess(actual, low..high) when actual < div(low+high,2) do
IO.puts "Is it: #{n = div(low+high,2)}"
guess(actual, low..n-1)
end

def guess(actual, _), do: IO.puts actual

end
``````

Just wanted to share my approach. Would like to know your thoughts

```defmodule Chop do
def guess(n, a..b) when (n == 0), do: 0
def guess(n, a..b) when (a == 0 or b == 0), do: "Error: Range"
def guess(n, a..b) when (n < a or n > b), do: "Error: Out of Range"
def guess(n, a..b) when (a == n or b == n), do: print(n)
def guess(n, a..b) when (n > a and n < b) do
y = div(a+b, 2)
print(y)
cond do
n == y -> IO.puts "Yes, it's #{y}"
n > y  -> guess(n, y+1..b)
n < y  -> guess(n, a..y-1)
end
end
defp print(n), do: IO.puts "Is it #{n}?"
end
```

I have to say, I struggled with this one since functional programming is very new too me. In the end, I took Chintan’s solution and tried to understand what’s happening there.

It’s new for me too, I agree that in the meaning of the book, the Nathan Solution is the closest solution on the training

Here is my solution:

``````
defmodule Chop do
@moduledoc false

def guess(number, a..b) when div((a + b), 2) === number do
guessed_number = div((a + b), 2)
IO.puts "Is it #{guessed_number}"
IO.puts "Yeah it is #{guessed_number} !!"
end

def guess(number, a..b) when number > div((a + b), 2) do
guessed_number = div((a + b), 2)
IO.puts "Is it #{guessed_number}"
guess(number, guessed_number..b)
end

def guess(number, a..b) when number < div((a + b), 2) do
guessed_number = div((a + b), 2)
IO.puts "Is it #{guessed_number}"
guess(number, a..guessed_number)
end

end

``````
``````defmodule Chop do
def guess(actual, from..to) do
myguess(actual, from, to, get_next_guess(from, to))
end

def get_next_guess(from, to) do
next_num = div(to + from, 2)
IO.puts "Is it #{next_num}"
next_num
end

defp myguess(actual, _, _, curr) when actual == curr, do: IO.puts(curr)
defp myguess(actual, _, to, curr) when curr < actual do
myguess(actual, curr, to, get_next_guess(curr, to))
end
defp myguess(actual, from, _, curr) when curr > actual do
myguess(actual, from, curr, get_next_guess(from, curr))
end
end
``````

defmodule Guess do def guess(guess) when guess === 200 do

``````    IO.puts "Congratulations!!! you guessed the Mystery number."
end
def guess(guess) when guess < 200 do

IO.puts "Your guess is lower than the Mystery number."
end
def guess(guess) when guess > 200 do

IO.puts "Your guess is higher than the Mystery number."
end
end
IO.puts "Guess the Mystery number, between 1 and 1000"
``````

My solution, with addition of range check from this thread. We still don’t need helper functions on this stage.

``````defmodule Chop do
def guess(n, a..b) when not n in a..b, do: IO.puts "No cheating, please"
def guess(n, a..b) when div(a + b, 2) > n do
n1 = div(a + b, 2)
IO.puts "It is #{n1}"
guess(n, a..(n1 - 1))
end
def guess(n, a..b) when div(a + b, 2) < n do
n1 = div(a + b, 2)
IO.puts "It is #{n1}"
guess(n, (n1 + 1)..b)
end
def guess(n, a..b) when div(a + b, 2) === n do
n1 = div(a + b, 2)
IO.puts "It is #{n1}"
n1
end
end
``````

Oh, and with pipe operator introduced later in the chapter my code can be cleaned from repetitions:

``````defmodule ChopPipe do
def guess(n, a..b) when not n in a..b, do: IO.puts "No cheating please"
def guess(n, a..b), do: guess_from(a..b) |> trace |> redirect(n, a..b)

defp guess_from(a..b), do: div(a + b, 2)

defp trace(n) do
IO.puts "It is #{n}"
n
end

defp redirect(guessed, n, a..b) when guessed > n, do: guess(n, a..(guessed - 1))
defp redirect(guessed, n, a..b) when guessed < n, do: guess(n, (guessed + 1)..b)
defp redirect(guessed, n, a..b) when guessed === n, do: guessed
end
``````

Well, this is my solution…

``````defmodule Chop do
def guess(n, a..b) do
IO.puts "Is it #{div(a+b, 2)}"
_guess(div(a+b, 2), n, a..b)
end

defp _guess(m, m, _), do: m

defp _guess(m, n, a..b) when m>n do
guess(n, a..m)
end

defp _guess(m, n, a..b) when m<n do
guess(n, m..b)
end
end
``````

My solution

defmodule Chop do

``````def guess(target, first..last) when div(first+last,2) == target do
IO.puts target
end
def guess(target, first..last) do
half = div(first+last,2)
IO.puts("is it #{half}")
if target > half do
guess(target, half..last)
else
guess(target, first..half)
end
end
``````

end

And here is mine:

``````defmodule Chop do
def guess(num, min..max) do
guess = div(min + max, 2)
IO.puts("Is it #{guess}?")
give(num, guess)
end

defp give(num, guess) when guess < num, do: guess(num, guess+1..num)
defp give(num, guess) when guess > num, do: guess(num, guess-1..num)
defp give(num, guess) when num == guess, do: num
end
``````

I’ve also added a couple of edge cases:

``````defmodule Chop do

def guess(number, min..max) when number > max or number < min  do
IO.puts "#{number} is not in range #{min}..#{max}"
end

def guess(number, min..max) when min == max and number == min do
IO.puts "That was easy:"
it_is! number
end

def guess(number, range) do
check_in_range number, range
end

defp check_in_range(number, range = min..max) do
possible = div max+min, 2
IO.puts "Is it #{possible}?"
is_it? number, possible, range
end

defp is_it?(number, possible, _) when number == possible do
it_is! number
end

defp is_it?(number, possible, _..max) when number > possible do
check_in_range number, possible+1..max
end

defp is_it?(number, possible, min.._) when number < possible do
check_in_range number, min..possible-1
end

defp it_is! number do
IO.puts "It's #{number}!"
end

end
``````
``````
defmodule Gosu do

def guess(x,a..b) when x == a do a end
def guess(x,a..b) when x == b do b end
def guess(x,a..b) when x in a..(a+div(b-a,2)) do
guess(x,a..(a+div(b-a,2)))
end
def guess(x,a..b) when x in (a+div(b-a,2))..b do
guess(x,(a+div(b-a,2))..b)
end

end

``````

I added an anonymous function to replace the traditional if case within the recursive control

``````defmodule Chop do
def guess(actual, range) do
first..last = range
my_guess = div(first+last,2)
IO.puts "is it #{my_guess}"
a = fn
(a,g) when a==g -> "It is #{a}"
(a,g) when a>g -> guess(a,my_guess..last)
(a,g) when a<g -> guess(a,first..my_guess)
end
a.(actual,my_guess)
end
end
``````

Here is my solution with the what has been covered in the book so far.

``````defmodule Chop do
def guess(actual, range = low..high) do
check_guess = fn
actual, actual, _range -> IO.puts("Is #{actual}")
actual, guess, low.._high when guess > actual -> guess(actual, low..guess)
actual, guess, _low..high -> guess(actual, guess..high)
end

guess = div(high + low, 2)
IO.puts("Is it #{guess}?")
check_guess.(actual, guess, range)
end
end
``````
You must be logged in to comment