From Undecidability Require Export PrettyBounds.SizeBounds.
Inductive sigTape (sig : Type) : Type :=
| LeftBlank (marked : bool)
| RightBlank (marked : bool)
| NilBlank (* always marked *)
| MarkedSymbol (s : sig)
| UnmarkedSymbol (s : sig).
Instance sigTape_eq (sig : Type) : eq_dec sig -> eq_dec (sigTape sig).
Definition isMarked (sig : Type) (s : sigTape sig) : bool :=
match s with
| LeftBlank marked => marked
| RightBlank marked => marked
| NilBlank => true
| MarkedSymbol _ => true
| UnmarkedSymbol _ => false
end.
Definition isNilBlank {sig : Type} (s : sigTape sig) : bool :=
match s with
NilBlank => true
| _ => false
end.
Definition isLeftBlank {sig : Type} (s : sigTape sig) : bool :=
match s with
| LeftBlank _  => true
| _ => false
end.
Definition isVoidBlank {sig : Type} (s : sigTape sig) : bool :=
match s with
| RightBlank _ => true
| _ => false
end.
Definition isSymbol {sig : Type} (s : sigTape sig) : bool :=
match s with
| UnmarkedSymbol _ | MarkedSymbol _ => true
| _ => false
end.
Definition encode_tape (sig : Type) (t : tape sig) : list (sigTape sig) :=
match t with
| niltape _ => [NilBlank]
| leftof r rs => LeftBlank true :: UnmarkedSymbol r :: map UnmarkedSymbol rs ++ [RightBlank false]
| midtape ls m rs => LeftBlank false :: map UnmarkedSymbol (rev ls) ++ MarkedSymbol m :: map UnmarkedSymbol rs ++ [RightBlank false]
| rightof l ls => LeftBlank false :: map UnmarkedSymbol (rev ls) ++ [UnmarkedSymbol l; RightBlank true]
end.
Instance Encode_tape (sig : Type) : codable (sigTape sig) (tape sig) :=
{|
encode := @encode_tape sig;
|}.
(* Compute encode_tape (niltape nat). *)
(* Compute encode_tape (midtape [3;2;1] 4 [5;6;7]). *)
(* Compute encode_tape (leftof 1 [2;3]). *)
(* Compute encode_tape (rightof 3 [2;1]). *)
(* Moving does not change the number of symbols. *)
Goal forall (sig : Type) (m : move) (t : tape sig), length (encode_tape (tape_move t m)) = length (encode_tape t).
Definition encode_tapes (sig : Type) (n : nat) (t : tapes sig n) :=
encode_list (@Encode_tape sig) (vector_to_list t).
Arguments encode_tapes {sig n}.
Instance Encode_tapes (sig : Type) (n : nat) : codable (sigList (sigTape sig)) (tapes sig n) :=
{|
encode := @encode_tapes sig n;
|}.
(* Compute encode_tapes [| niltape nat; midtape [3;2;1] 4 [5;6;7]; leftof 1 [2;3];rightof 3 [2;1] |]. *)
Fixpoint split_vector {X : Type} {n : nat} (v : Vector.t X n) (k : nat) : Vector.t X (min k n) * Vector.t X (n-k).
(* Compute split_vector [| 1; 2; 3; 4 |] 1. *)
(* Compute let (x,y) := split_vector [| 1; 2; 3; 4 |] 1 in Vector.append x y. *)

Lemma sizeOfTape_encodeTape_le sig' (t : tape sig') :
| encode_tape t | <= 2 + sizeOfTape t.