src/HOL/ex/Puzzle.thy
author wenzelm
Fri, 15 Aug 2008 15:50:52 +0200
changeset 27885 76b51cd0a37c
parent 27789 1bf827e3258d
child 27964 1e0303048c0b
permissions -rw-r--r--
renamed T.source_of' to T.source_position_of;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2222
a3fb552f10e3 Added Lagrang. Modified comment.
nipkow
parents: 1476
diff changeset
     1
(*  Title:      HOL/ex/Puzzle.thy
969
b051e2fc2e34 converted ex with curried function application
clasohm
parents:
diff changeset
     2
    ID:         $Id$
1476
608483c2122a expanded tabs; incorporated Konrad's changes
clasohm
parents: 1376
diff changeset
     3
    Author:     Tobias Nipkow
969
b051e2fc2e34 converted ex with curried function application
clasohm
parents:
diff changeset
     4
*)
b051e2fc2e34 converted ex with curried function application
clasohm
parents:
diff changeset
     5
27789
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
     6
header {* Fun with Functions *}
17388
495c799df31d tuned headers etc.;
wenzelm
parents: 16417
diff changeset
     7
16417
9bc16273c2d4 migrated theory headers to new format
haftmann
parents: 14126
diff changeset
     8
theory Puzzle imports Main begin
13116
baabb0fd2ccf converted to Isar
paulson
parents: 8018
diff changeset
     9
27789
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    10
text{* From \emph{Solving Mathematical Problems} by Terence Tao. He quotes
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    11
Greitzer's \emph{Interational Mathematical Olympiads 1959--1977} as the
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    12
original source. Was first brought to our attention by Herbert Ehler who
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    13
provided a similar proof. *}
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    14
13116
baabb0fd2ccf converted to Isar
paulson
parents: 8018
diff changeset
    15
27789
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    16
theorem identity1: fixes f :: "nat \<Rightarrow> nat"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    17
assumes fff: "!!n. f(f(n)) < f(Suc(n))"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    18
shows "f(n) = n"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    19
proof -
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    20
  { fix m n have key: "n \<le> m \<Longrightarrow> n \<le> f(m)"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    21
    proof(induct n arbitrary: m)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    22
      case 0 show ?case by simp
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    23
    next
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    24
      case (Suc n)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    25
      hence "m \<noteq> 0" by simp
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    26
      then obtain k where [simp]: "m = Suc k" by (metis not0_implies_Suc)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    27
      have "n \<le> f(k)" using Suc by simp
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    28
      hence "n \<le> f(f(k))" using Suc by simp
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    29
      also have "\<dots> < f(m)" using fff by simp
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    30
      finally show ?case by simp
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    31
    qed }
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    32
  hence "!!n. n \<le> f(n)" by simp
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    33
  hence "!!n. f(n) < f(Suc n)" by(metis fff order_le_less_trans)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    34
  hence "f(n) < n+1" by (metis fff lift_Suc_mono_less_iff[of f] Suc_plus1)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    35
  with `n \<le> f(n)` show "f n = n" by arith
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    36
qed
13116
baabb0fd2ccf converted to Isar
paulson
parents: 8018
diff changeset
    37
baabb0fd2ccf converted to Isar
paulson
parents: 8018
diff changeset
    38
27789
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    39
text{* From \emph{Solving Mathematical Problems} by Terence Tao. He quotes
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    40
the \emph{Australian Mathematics Competition} 1984 as the original source.
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    41
Possible extension:
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    42
Should also hold if the range of @{text f} is the reals!
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    43
*}
13116
baabb0fd2ccf converted to Isar
paulson
parents: 8018
diff changeset
    44
27789
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    45
lemma identity2: fixes f :: "nat \<Rightarrow> nat"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    46
assumes "f(k) = k" and "k \<ge> 2"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    47
and f_times: "\<And>m n. f(m*n) = f(m)*f(n)"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    48
and f_mono: "\<And>m n. m<n \<Longrightarrow> f m < f n"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    49
shows "f(n) = n"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    50
proof -
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    51
  have 0: "f(0) = 0"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    52
    by (metis f_mono f_times mult_1_right mult_is_0 nat_less_le nat_mult_eq_cancel_disj not_less_eq)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    53
  have 1: "f(1) = 1"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    54
    by (metis f_mono f_times gr_implies_not0 mult_eq_self_implies_10 nat_mult_1_right zero_less_one)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    55
  have 2: "f 2 = 2"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    56
  proof -
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    57
    have "2 + (k - 2) = k" using `k \<ge> 2` by arith
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    58
    hence "f(2) \<le> 2"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    59
      using mono_nat_linear_lb[of f 2 "k - 2",OF f_mono] `f k = k`
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    60
      by simp arith
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    61
    thus "f 2 = 2" using 1 f_mono[of 1 2] by arith
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    62
  qed
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    63
  show ?thesis
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    64
  proof(induct rule:less_induct)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    65
    case (less i)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    66
    show ?case
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    67
    proof cases
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    68
      assume "i\<le>1" thus ?case using 0 1 by (auto simp add:le_Suc_eq)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    69
    next
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    70
      assume "~i\<le>1"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    71
      show ?case
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    72
      proof cases
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    73
	assume "i mod 2 = 0"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    74
	hence "EX k. i=2*k" by arith
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    75
	then obtain k where "i = 2*k" ..
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    76
	hence "0 < k" and "k<i" using `~i\<le>1` by arith+
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    77
	hence "f(k) = k" using less(1) by blast
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    78
	thus "f(i) = i" using `i = 2*k` by(simp add:f_times 2)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    79
      next
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    80
	assume "i mod 2 \<noteq> 0"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    81
	hence "EX k. i=2*k+1" by arith
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    82
	then obtain k where "i = 2*k+1" ..
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    83
	hence "0<k" and "k+1<i" using `~i\<le>1` by arith+
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    84
	have "2*k < f(2*k+1)"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    85
	proof -
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    86
	  have "2*k = 2*f(k)" using less(1) `i=2*k+1` by simp
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    87
	  also have "\<dots> = f(2*k)" by(simp add:f_times 2)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    88
	  also have "\<dots> < f(2*k+1)" using f_mono[of "2*k" "2*k+1"] by simp
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    89
	  finally show ?thesis .
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    90
	qed
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    91
	moreover
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    92
	have "f(2*k+1) < 2*(k+1)"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    93
	proof -
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    94
	  have "f(2*k+1) < f(2*k+2)" using f_mono[of "2*k+1" "2*k+2"] by simp
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    95
	  also have "\<dots> = f(2*(k+1))" by simp
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    96
	  also have "\<dots> = 2*f(k+1)" by(simp only:f_times 2)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    97
	  also have "f(k+1) = k+1" using less(1) `i=2*k+1` `~i\<le>1` by simp
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    98
	  finally show ?thesis .
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
    99
	qed
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   100
	ultimately show "f(i) = i" using `i = 2*k+1` by arith
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   101
      qed
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   102
    qed
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   103
  qed
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   104
qed
13116
baabb0fd2ccf converted to Isar
paulson
parents: 8018
diff changeset
   105
27789
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   106
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   107
text{* The only total model of a naive recursion equation of factorial on
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   108
integers is 0 for all negative arguments: *}
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   109
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   110
theorem ifac_neg0: fixes ifac :: "int \<Rightarrow> int"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   111
assumes ifac_rec: "!!i. ifac i = (if i=0 then 1 else i*ifac(i - 1))"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   112
shows "i<0 \<Longrightarrow> ifac i = 0"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   113
proof(rule ccontr)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   114
  assume 0: "i<0" "ifac i \<noteq> 0"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   115
  { fix j assume "j \<le> i"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   116
    have "ifac j \<noteq> 0"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   117
      apply(rule int_le_induct[OF `j\<le>i`])
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   118
       apply(rule `ifac i \<noteq> 0`)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   119
      apply (metis `i<0` ifac_rec linorder_not_le mult_eq_0_iff)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   120
      done
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   121
  } note below0 = this
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   122
  { fix j assume "j<i"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   123
    have "1 < -j" using `j<i` `i<0` by arith
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   124
    have "ifac(j - 1) \<noteq> 0" using `j<i` by(simp add: below0)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   125
    then have "\<bar>ifac (j - 1)\<bar> < (-j) * \<bar>ifac (j - 1)\<bar>" using `j<i`
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   126
      mult_le_less_imp_less[OF order_refl[of "abs(ifac(j - 1))"] `1 < -j`]
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   127
      by(simp add:mult_commute)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   128
    hence "abs(ifac(j - 1)) < abs(ifac j)"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   129
      using `1 < -j` by(simp add: ifac_rec[of "j"] abs_mult)
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   130
  } note not_wf = this
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   131
  let ?f = "%j. nat(abs(ifac(i - int(j+1))))"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   132
  obtain k where "\<not> ?f (Suc k) < ?f k"
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   133
    using wf_no_infinite_down_chainE[OF wf_less, of "?f"] by blast
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   134
  moreover have "i - int (k + 1) - 1 = i - int (Suc k + 1)" by arith
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   135
  ultimately show False using not_wf[of "i - int(k+1)"]
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   136
    by (simp only:) arith
1bf827e3258d added lemmas
nipkow
parents: 23813
diff changeset
   137
qed
13116
baabb0fd2ccf converted to Isar
paulson
parents: 8018
diff changeset
   138
969
b051e2fc2e34 converted ex with curried function application
clasohm
parents:
diff changeset
   139
end