summaryrefslogtreecommitdiff
path: root/src/Problem16.agda
blob: d327602845f44670625922a727dc384abbd714de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{-# OPTIONS --safe #-}

module Problem16 where

open import Data.Fin
open import Data.Nat using (ℕ; zero; suc)
open import Data.Nat.Properties using (0≢1+n)
open import Data.Fin.Properties
open import Data.Product hiding (map)
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary
open import Function

variable n : ℕ

open ≡-Reasoning

Inj : (Fin n → Fin n) → Set
Inj f = ∀ i j → f i ≡ f j → i ≡ j

Sur : (Fin n → Fin n) → Set
Sur f = ∀ x → ∃[ y ] f y ≡ x

goal : ∀ n (f : Fin n → Fin n) → Inj f → Sur f
goal (suc n) f inj x with f zero ≟ x
... | yes prf = zero , prf
... | no f0≢x =
  let (z , prf) = goal n f′ f′-inj (punchOut f0≢x) in
  suc z ,
  (begin
    f (suc z)                                 ≡˘⟨ punchIn-punchOut (f0≢f[1+i] z) ⟩
    punchIn (f zero) (punchOut (f0≢f[1+i] z)) ≡⟨ cong (punchIn (f zero)) prf ⟩
    punchIn (f zero) (punchOut (f0≢x))        ≡⟨ punchIn-punchOut f0≢x ⟩
    x                                         ∎)
  where
  f0≢f[1+i] : ∀ i → f zero ≢ f (suc i)
  f0≢f[1+i] i prf = 0≢1+n (cong toℕ (inj zero (suc i) prf))

  f′ : Fin n → Fin n
  f′ = punchOut ∘ f0≢f[1+i]

  f′-inj : Inj f′
  f′-inj i j prf =
    suc-injective $′
    inj (suc i) (suc j) $′
    punchOut-injective (f0≢f[1+i] i) (f0≢f[1+i] j) prf