Hi, Habr.
The other day, I went to an interview in one serious company, and there they offered me to turn over a simply connected list. Unfortunately, this task took the entire first round of the interview, and at the end of the interview, the interviewer said that everyone else was sick today, and therefore I can go home. Nevertheless, the whole process of solving this problem, including a couple of options for the algorithm and their subsequent discussion, as well as discussions about what the list turning is, under the cat.
The interviewer was pretty nice and friendly:
- Well, let's first solve this problem: a singly connected list is given, you need to reverse it.
- I'll do it now! And in what language is it better to do this?
- Which one is more convenient for you?
I interviewed a C ++ developer, but to describe the algorithms on lists, this is not the best language. In addition, I read somewhere that at the interviews you first need to offer an ineffective solution, and then improve it sequentially, so I opened the laptop, launched vim and the interpreter and sketched this code:
revDumb : List a -> List a revDumb [] = [] revDumb (x :: xs) = revDumb xs ++ [x]
, , , - , , :
revOnto : List a -> List a -> List a revOnto acc [] = acc revOnto acc (x :: xs) = revOnto (x :: acc) xs revAcc : List a -> List a revAcc = revOnto []
โ , , , .
- , . , ( ?) - , :
โ , , , , , , , .
revsEq : (xs : List a) -> revAcc xs = revDumb xs
, :
โ , case split .
โ generate definition, case split, obvious proof search โ
revsEq : (xs : List a) -> revAcc xs = revDumb xs revsEq [] = Refl revsEq (x :: xs) = ?revsEq_rhs_1
, , , :
โ , , , . , , , :
revsEq : (xs : List a) -> revAcc xs = revDumb xs revsEq [] = Refl revsEq (x :: xs) = let rec = revsEq xs in ?wut
โ ?wut
,
rec : revOnto [] xs = revDumb xs -------------------------------------- wut : revOnto [x] xs = revDumb xs ++ [x]
โ revDumb xs
, rec
. :
revsEq (x :: xs) = let rec = revsEq xs in rewrite sym rec in ?wut
-------------------------------------- wut : revOnto [x] xs = revOnto [] xs ++ [x]
โ c :
lemma1 : (x0 : a) -> (xs : List a) -> revOnto [x0] xs = revOnto [] xs ++ [x0]
generate definition, case split xs
, obvious proof search
lemma1 : (x0 : a) -> (xs : List a) -> revOnto [x0] xs = revOnto [] xs ++ [x0] lemma1 x0 [] = Refl lemma1 x0 (x :: xs) = ?lemma1_rhs_2
โ , . lemma1 x xs
, lemma1 x0 xs
. , , ,
lemma1 x0 (x :: xs) = let rec = lemma1 x xs in ?wut
?wut
:
rec : revOnto [x] xs = revOnto [] xs ++ [x] -------------------------------------- wut : revOnto [x, x0] xs = revOnto [x] xs ++ [x0]
โ revOnto [x] xs
rec
. :
lemma1 x0 (x :: xs) = let rec = lemma1 x xs in rewrite rec in ?wut
โ , :
-------------------------------------- wut : revOnto [x, x0] xs = (revOnto [] xs ++ [x]) ++ [x0]
โ , . :
lemma1 x0 (x :: xs) = let rec = lemma1 x xs in rewrite rec in rewrite sym $ appendAssociative (revOnto [] xs) [x] [x0] in ?wut
โ -:
-------------------------------------- wut : revOnto [x, x0] xs = revOnto [] xs ++ [x, x0]
โ ! , , , . , , :
lemma2 : (acc, lst : List a) -> revOnto acc lst = revOnto [] lst ++ acc
IDE . case split lst
, acc
, revOnto
lst
:
lemma2 : (acc, lst : List a) -> revOnto acc lst = revOnto [] lst ++ acc lemma2 acc [] = Refl lemma2 acc (x :: xs) = ?wut1
wut1
-------------------------------------- wut1 : revOnto (x :: acc) xs = revOnto [x] xs ++ acc
:
lemma2 acc (x :: xs) = let rec = lemma2 (x :: acc) xs in ?wut1
rec : revOnto (x :: acc) xs = revOnto [] xs ++ x :: acc -------------------------------------- wut1 : revOnto (x :: acc) xs = revOnto [x] xs ++ acc
rec
:
lemma2 acc (x :: xs) = let rec = lemma2 (x :: acc) xs in rewrite rec in ?wut1
-------------------------------------- wut1 : revOnto [] xs ++ x :: acc = revOnto [x] xs ++ acc
โ - . , lemma1
, , lemma2
, lemma1 x xs
, lemma2 [x] xs
:
lemma2 acc (x :: xs) = let rec1 = lemma2 (x :: acc) xs in let rec2 = lemma2 [x] xs in rewrite rec1 in rewrite rec2 in ?wut1
:
-------------------------------------- wut1 : revOnto [] xs ++ x :: acc = (revOnto [] xs ++ [x]) ++ acc
, :
lemma2 : (acc, lst : List a) -> revOnto acc lst = revOnto [] lst ++ acc lemma2 acc [] = Refl lemma2 acc (x :: xs) = let rec1 = lemma2 (x :: acc) xs in let rec2 = lemma2 [x] xs in rewrite rec1 in rewrite rec2 in rewrite sym $ appendAssociative (revOnto [] xs) [x] acc in Refl
โ , lemma1
, , lemma2
lemma
. , , , :
lemma : (acc, lst : List a) -> revOnto acc lst = revOnto [] lst ++ acc lemma acc [] = Refl lemma acc (x :: xs) = let rec1 = lemma (x :: acc) xs in let rec2 = lemma [x] xs in rewrite rec1 in rewrite rec2 in rewrite sym $ appendAssociative (revOnto [] xs) [x] acc in Refl revsEq : (xs : List a) -> revAcc xs = revDumb xs revsEq [] = Refl revsEq (x :: xs) = let rec = revsEq xs in rewrite sym rec in lemma [x] xs
15, - , .
โ , , - .
โ , , . ! , ? ?!
โ ! , ! , , ? ยซ ยป? : xs
โ , xs'
ยซยป , , . !
revCorrect : (xs : List a) -> (f : b -> a -> b) -> (init : b) -> foldl f init (revDumb xs) = foldr (flip f) init xs
โ , revDumb
revAcc
( forall xs. revDumb xs = revAcc xs
, , , , ), , , revDumb
.
,
revCorrect : (xs : List a) -> (f : b -> a -> b) -> (init : b) -> foldl f init (revDumb xs) = foldr (flip f) init xs revCorrect [] f init = Refl revCorrect (x :: xs) f init = let rec = revCorrect xs f init in ?wut
:
rec : foldl f init (revDumb xs) = foldr (flip f) init xs -------------------------------------- wut : foldl f init (revDumb xs ++ [x]) = f (foldr (flip f) init xs) x
โ :
revCorrect (x :: xs) f init = let rec = revCorrect xs f init in rewrite sym rec in ?wut
-------------------------------------- wut : foldl f init (revDumb xs ++ [x]) = f (foldl f init (revDumb xs)) x
โ revDumb xs
. : f
f
, . :
foldlRhs : (f : b -> a -> b) -> (init : b) -> (x : a) -> (xs : List a) -> foldl f init (xs ++ [x]) = f (foldl f init xs) x
โ , . :
foldlRhs : (f : b -> a -> b) -> (init : b) -> (x : a) -> (xs : List a) -> foldl f init (xs ++ [x]) = f (foldl f init xs) x foldlRhs f init x [] = Refl foldlRhs f init x (y :: xs) = foldlRhs f (f init y) x xs revCorrect : (xs : List a) -> (f : b -> a -> b) -> (init : b) -> foldl f init (revDumb xs) = foldr (flip f) init xs revCorrect [] f init = Refl revCorrect (x :: xs) f init = let rec = revCorrect xs f init in rewrite sym rec in foldlRhs f init x (revDumb xs)
โ - ?
โ . , .
โ โฆ , , . , , , , .
, - .