summaryrefslogtreecommitdiff
path: root/src/Problem4.agda
blob: 3215dd000da5ef9e95eb8ba4e9ac6facfa212f48 (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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
{-# OPTIONS --safe #-}

module Problem4 where

open import Data.Integer renaming (suc to sucℤ; pred to predℤ) hiding (_≤_)
open import Data.Nat renaming (_+_ to _ℕ+_)
open import Data.Nat.Properties using (  +-monoʳ-≤;  +-monoˡ-≤; +-suc; ≤-trans; module ≤-Reasoning )
open import Data.Integer.Properties using ( +-inverseʳ )
open import Data.Product
open import Relation.Binary.PropositionalEquality
-- The theorems explicitly imported above were useful to prove this!

-- the below theorems are just used to prove the helpers
open import Data.Integer.Properties using ( ∣m+n∣≤∣m∣+∣n∣; +-assoc; neg-distrib-+; +-comm; +-identityʳ )

Point = ℤ × ℤ

up : Point → Point
up (x , y) = (x , sucℤ y)
down : Point → Point
down (x , y) = (x , predℤ y)
left : Point → Point
left (x , y) = (predℤ x , y)
right : Point → Point
right (x , y) = (sucℤ x , y)

data OrthoPath (p : Point) : Point → Set where
   move-up : ∀ {q} → OrthoPath (up p) q → OrthoPath p q
   move-down : ∀ {q} → OrthoPath (down p) q → OrthoPath p q
   move-left : ∀ {q} → OrthoPath (left p) q → OrthoPath p q
   move-right : ∀ {q} → OrthoPath (right p) q → OrthoPath p q
   stop : OrthoPath p p

path-length : ∀{p q} → OrthoPath p q → ℕ
path-length (move-up p) = suc (path-length p)
path-length (move-down p) = suc (path-length p)
path-length (move-left p) = suc (path-length p)
path-length (move-right p) = suc (path-length p)
path-length stop = 0

manhattan : Point → Point → ℕ
manhattan (x₁ , y₁) (x₂ , y₂) = ∣ (x₂ - x₁) ∣ ℕ+ ∣ (y₂ - y₁) ∣

helper-sucℤ : ∀(a b : ℤ) → ∣ (a - b) ∣ ≤ suc ∣ (a - sucℤ b) ∣
helper-sucℤ a b rewrite
    sym (+-identityʳ (- b))
  | sym (+-assoc (- b) (- 1ℤ) 1ℤ)
  | sym (+-comm (- 1ℤ) (- b))
  | sym (neg-distrib-+ 1ℤ b)
  | sym (+-assoc a (- sucℤ b) 1ℤ)
  | +-comm (a - sucℤ b) 1ℤ
  = ∣m+n∣≤∣m∣+∣n∣ (1ℤ) (a - sucℤ b)

helper-predℤ : ∀(a b : ℤ) → ∣ (a - b) ∣ ≤ suc ∣ (a - predℤ b) ∣
helper-predℤ a b rewrite
    sym (+-identityʳ (- b))
  | sym (+-assoc (- b) 1ℤ -1ℤ)
  | sym (+-comm 1ℤ (- b))
  | sym (neg-distrib-+ -1ℤ b)
  | sym (+-assoc a (- predℤ b) -1ℤ )
  | +-comm (a - predℤ b) -1ℤ
  = ∣m+n∣≤∣m∣+∣n∣ (-1ℤ) (a - predℤ b)

open ≤-Reasoning

goal : ∀(p q : Point) → (path : OrthoPath p q) → manhattan p q ≤ path-length path
goal p@(px , py) q@(qx , qy) (move-up path) = begin
  manhattan p q                           ≡⟨⟩
  ∣ (qx - px) ∣ ℕ+ ∣ (qy - py) ∣          ≤⟨ +-monoʳ-≤ ∣ (qx - px) ∣ (helper-sucℤ qy py) ⟩
  ∣ (qx - px) ∣ ℕ+ suc ∣ (qy - sucℤ py) ∣ ≡⟨ +-suc ∣ (qx - px) ∣ ∣ (qy - sucℤ py) ∣ ⟩
  suc ∣ (qx - px) ∣ ℕ+ ∣ (qy - sucℤ py) ∣ ≡⟨⟩
  suc (manhattan (up p) q)                ≤⟨ s≤s (goal (up p) q path) ⟩
  suc (path-length path)                  ∎
goal p@(px , py) q@(qx , qy) (move-down path) = begin
  manhattan p q                            ≡⟨⟩
  ∣ (qx - px) ∣ ℕ+ ∣ (qy - py) ∣           ≤⟨ +-monoʳ-≤ ∣ (qx - px) ∣ (helper-predℤ qy py) ⟩
  ∣ (qx - px) ∣ ℕ+ suc ∣ (qy - predℤ py) ∣ ≡⟨ +-suc ∣ (qx - px) ∣ ∣ (qy - predℤ py) ∣ ⟩
  suc ∣ (qx - px) ∣ ℕ+ ∣ (qy - predℤ py) ∣ ≡⟨⟩
  suc (manhattan (down p) q)               ≤⟨ s≤s (goal (down p) q path) ⟩
  suc (path-length path)                   ∎
goal p@(px , py) q@(qx , qy) (move-left path) = begin
  manhattan p q                            ≡⟨⟩
  ∣ (qx - px) ∣ ℕ+ ∣ (qy - py) ∣           ≤⟨ +-monoˡ-≤ ∣ (qy - py) ∣ (helper-predℤ qx px) ⟩
  suc ∣ (qx - predℤ px) ∣ ℕ+ ∣ (qy - py) ∣ ≡⟨⟩
  suc (manhattan (left p) q)               ≤⟨ s≤s (goal (left p) q path) ⟩
  suc (path-length path)                   ∎
goal p@(px , py) q@(qx , qy) (move-right path) = begin
  manhattan p q                           ≡⟨⟩
  ∣ (qx - px) ∣ ℕ+ ∣ (qy - py) ∣          ≤⟨ +-monoˡ-≤ ∣ (qy - py) ∣ (helper-sucℤ qx px) ⟩
  suc ∣ (qx - sucℤ px) ∣ ℕ+ ∣ (qy - py) ∣ ≡⟨⟩
  suc (manhattan (right p) q)             ≤⟨ s≤s (goal (right p) q path) ⟩
  suc (path-length path)                  ∎
goal p@(px , py) .p stop = begin
  manhattan p p                  ≡⟨⟩
  ∣ (px - px) ∣ ℕ+ ∣ (py - py) ∣ ≡⟨ cong₂ (λ ◌ᵃ ◌ᵇ → ∣ ◌ᵃ ∣ ℕ+ ∣ ◌ᵇ ∣) (+-inverseʳ px) (+-inverseʳ py) ⟩
  0 ℕ+ 0                         ≡⟨⟩
  0                              ∎