How to deploy a singly-linked interview list

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.







image







We solve the problem



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)
      
      





โ€” - ?

โ€” . , .

โ€” โ€ฆ , , . , , , , .







, - .








All Articles