description: write a function that, given integers a and b, returns an integer x such that a + x = b

function_signature: def solveAdd (a b:Int): Int

theorem_signature: theorem solveAdd_correct (a b: Int): a + (solveAdd a b) =b


description: write a function that, given integer a, returns an integer x such that a + x = 0

function_signature: def solveAdd0(a:Int): Int

theorem_signature: theorem solveAdd0_correct(a: Int): a +(solveAdd0 a)=0


description: write a function that, given integers a and b, returns an integer x such that a - x = b

function_signature: def solveSub(a b:Int): Int

theorem_signature: theorem solveSub_correct(a b:Int): a - (solveSub a b)=b


description: write a function that, given rationals a and b, return some x such that a*x=b. if no solution exists, return none

function_signature: def solve1x1(a b: Rat): Option Rat

theorem_signature: theorem solve1x1_correct(a b:Rat): (∃ x, a*x=b) -> a * (solve1x1 a b).get! =b

theorem2_signature: theorem solve1x1_none(a b:Rat): (Not (∃ x, a*x=b)) -> solve1x1 a b=none


description: write a function that, given rational a, returns a rational x such that a*x=1. If no solution exists, return 0.

function_signature: def solveMul(a: Rat): Rat

theorem_signature: theorem solveMul_correct(a:Rat): (∃ x, a*x=1)->a * (solveMul a)=1

theorem2_signature: theorem solveMul_nosol (a:Rat): (Not (∃ x, a*x=1)) ->solveMul a =0


description: write a function that, given rationals a and b, both not equal to zero, return x such that a/x=b.

function_signature: def solveDiv(a b:Rat) (ha: a≠ 0)(hb: b≠ 0): Rat

theorem_signature:
theorem solveDiv_correct(a b:Rat)(ha:a≠ 0)(hb: b≠ 0):
a / (solveDiv a b ha hb)= b


description: write a function isPrime that given a natural number a, returns true if and only if a is prime.

function_signature: def isPrime(a: Nat): Bool

theorem_signature: theorem isPrime_correct(a: Nat): (isPrime a)=True <-> Nat.Prime a


description: write a function that given a natrual number a and a prime number p, returns a natural number x such that (a*x)%p=1. if no solution exists, return none.

function_signature: def modInv(a: Nat) (p:Nat)(hp:p.Prime): Option Nat

theorem_signature:
theorem modInv_correct(a:Nat) (p:Nat)(hp:p.Prime):
  (∃ x:Nat, (a*x)%p=1)->(a*(modInv a p hp).get!)%p=1

theorem2_signature: theorem modInv_none(a:Nat) (p:Nat)(hp:p.Prime): (Not (∃ x, (a*x)%p=1))-> modInv a p hp=none


description: write a function that given a natural number a, a>1, find the minimum factor of a that is not 1.

function_signature: def minFac(a:Nat) (h: a>1): Nat

theorem_signature: theorem minFac_isfac(a:Nat)(h: a>1): ( (minFac a h) ∣a) ∧(minFac a h>1)

theorem2_signature: theorem minFac_ismin(a:Nat)(h:a>1): Not (∃ y>1,( y ∣ a) ∧y<minFac a h)


description: write a function that, given rational number coordinates of two points x1, y1 and x2, y2, return the rational number coordinates of a point (xmid, ymid) such that: the distance betwee (xmid,ymid) and (x1, y1) is equal to the distance between (xmid,ymid) and (x2,y2), which is equal to half of the distance between (x1, y1) and (x2, y2).

function_signature: def midPoint (x1 y1 x2 y2: Rat):Rat × Rat

theorem_signature:
def distSq( x1  y1 x2 y2: Rat):Rat:=
  (x1-x2)^2 + (y1-y2)^2

theorem midPoint_correct (x1 y1 x2 y2: Rat)
: let (xmid,ymid) :=midPoint x1 y1 x2 y2
distSq xmid ymid x1 y1=distSq xmid ymid x2 y2
∧ 4*(distSq xmid ymid x1 y1)=distSq x1  y1 x2 y2


description: write a function that, given natural numbers a and b, computes their greatest common denominator.

function_signature: def GCD(a b:Nat):Nat

theorem_signature:
theorem gcd_is_div (x y: Nat):
  (p: x > 0)→ ((GCD x y) ∣ x) ∧ ((GCD x y) ∣ y)

theorem2_signature:
theorem gcd_is_greatest (x y: Nat):
  (x>0) → Not (∃ z: Nat, z∣ x ∧ z∣ y ∧ z> GCD x y )


description: write a function that, given natural number t, find the minimum n such that 1+2+…+n>=t.

function_signature: def solveProg(t:Nat):Nat

theorem_signature: theorem solveProg_isgeq(t:Nat): (solveProg t)*((solveProg t)+1) >= t*2

theorem2_signature: theorem solveProg_ismin(t:Nat): Not (∃ y< (solveProg t), y*(y+1)>=t*2)


description: write a function that, given natural numbers a and t, with a>1, find the minimum n such that a^0+a^1+..a^n >=t.

function_signature: def solveGeom(a t:Nat)(h:a>1):Nat

theorem_signature: theorem solveGeom_isgeq(a t:Nat)(h:a>1): a^((solveGeom a t h)+1)-1 >=t*(a-1)

theorem2_signature: theorem solveGeom_ismin(a t:Nat)(h:a>1): Not (∃ y<solveGeom a t h, a^(y+1)-1>= t*(a-1))


description: write a function that, given natural number t, find the minimum n such that n*n>=t.

function_signature: def solveSquare(t:Nat): Nat

theorem_signature: theorem solveSquare_isgeq(t:Nat): (solveSquare t)*(solveSquare t)>=t

theorem2_signature: theorem solveSquare_ismin(t:Nat): Not (∃ y< (solveSquare t), y*y>=t)


description: Implement the following in lean 4. Given a binary operator op, we define the function f : Nat->Nat to be: f 0 =1; f 1=1; f n = op (f (n-1)) (f (n-2)). Write a lean 4 function that, given the op and the natural number n as arguments, computes f n. Additionally, op returns a value wrapped in a monad. Your function should have the signature def f [Monad m] (op: Nat->Nat->(m Nat)) (n: Nat): (m Nat) :=

function_signature: def f[Monad m] (op: Nat->Nat->(m Nat)) (n: Nat): (m Nat)

theorem_signature:
theorem f_base (op : Nat → Nat → Id Nat) :
    (f op 0 = pure 1) ∧  (f op 1 = pure 1)

theorem2_signature: theorem f_recursive (op : Nat → Nat → Id Nat) (n : Nat) : f op (n+2) =do {op (←  f op (n+1)) (←  f op n) }


description: write a function that, given a List of integers, return the list in reverse order.

function_signature: def rev(xs: List Int): List Int

theorem_signature:
theorem reverse_correct(xs:List Int):
  xs.length=(rev xs).length ∧
  ∀ i<xs.length, xs[i]! =(rev xs)[xs.length-1-i]!


description: write a function that, given a List of integers, finds its maximum

function_signature: def findMax (xs : List Int) : Option Int

theorem_signature:
theorem findMax_correct(x: Int) (xs : List Int):
  ∃ max∈ (x::xs),
    And (findMax (x::xs) = some max) (∀ y ∈ (x::xs) , y ≤ max)

theorem2_signature: theorem findMax_base : findMax [] = none


description: write a function that, given a List of integers, finds the minimum

function_signature: def findMin (xs : List Int) : Option Int

theorem_signature:
theorem findMin_correct(x: Int) (xs : List Int):
  ∃ min∈ (x::xs),
    And (findMin (x::xs) = some min) (∀ y ∈ (x::xs) , y >= min)

theorem2_signature: theorem findMin_base : findMin [] = none


description: write a function that, given an integer x and a List of integers, returns true if and only if x is in the List

function_signature: def isIn (x:Int) (xs: List Int):Bool

theorem_signature:
def isIn_correct (x:Int)(xs:List Int):
  isIn x xs = true ↔ x∈ xs


description: write a function that, given an integer x and a List of integers, returns the number of times that x appears in the list.

function_signature: def countEq (x:Int)(xs:List Int):Nat

theorem_signature:
def countEq_correct (x:Int)(xs:List Int):
  List.count x xs = countEq x xs


description: write a function that, given a List of integers and a predicate function p that takes an integer and returns a boolean, returns an element of the list x if p x = true. If such x does not exist, return none

function_signature: def findIf(xs:List Int)(p:Int->Bool):Option Int

theorem_signature:
theorem findIf_some(xs:List Int)(p:Int->Bool):
  (∃ x∈ xs, p x) -> ∃ y∈ xs, findIf xs p=some y ∧ p y

theorem2_signature:
theorem findIf_none(xs:List Int)(p:Int->Bool):
  (¬ ∃ y∈ xs, p y =true)-> findIf xs p=none


description: write a function that, given a List of integers and a predicate function p that takes an integer and returns a boolean, returns another list consisting of elements  x of the original list such that  p x = true.

function_signature: def filterIf(xs:List Int)(p:Int->Bool):List Int

theorem_signature:
theorem filterIf_correct(xs:List Int)(p:Int->Bool):
  filterIf xs p = List.filter p xs


description: write a function that, given a List of integers xs and a function f:Int->Int, returns a List of integers whose i-th element is f xs[i]

function_signature: def mapInt(xs:List Int)(f:Int->Int):List Int

theorem_signature:
theorem mapInt_correct(xs:List Int)(f:Int->Int)
: (mapInt xs f).length=xs.length
∧  ∀ i:Fin xs.length, (mapInt xs f)[i]! = f xs[i]


description: Write a function that, given two lists of integers, find their longest common prefix.

function_signature:
def isPrefix (p xs:List α):=
  List.take p.length xs = p

/- longest common prefix for a pair of lists-/
def lcpPair:(xs ys:List Int )
->{zs:List Int//isPrefix zs xs∧ isPrefix zs ys
   ∧ (∀zz, isPrefix zz xs∧ isPrefix zz ys->zz.length<=zs.length)}