56 // |
85 // |
57 |
86 |
58 import scala.util._ // Try,... |
87 import scala.util._ // Try,... |
59 import io.Source // fromURL |
88 import io.Source // fromURL |
60 |
89 |
61 val my_url = "https://nms.kcl.ac.uk/christian.urban/" |
90 //val my_url = "https://nms.kcl.ac.uk/christian.urban/" |
62 |
91 val my_url = "https://urbanchr.github.io/" |
63 Source.fromURL(my_url)("ISO-8859-1").mkString |
92 |
64 Source.fromURL(my_url)("ISO-8859-1").getLines().toList |
93 println(Try(Source.fromURL(my_url)(using "ISO-8859-1").mkString).toOption) |
65 |
94 |
66 Try(Source.fromURL(my_url)("ISO-8859-1").mkString).getOrElse("") |
95 .mkString |
67 |
96 Source.fromURL(my_url)(using "ISO-8859-1").getLines().toList |
68 Try(Some(Source.fromURL(my_url)("ISO-8859-1").mkString)).getOrElse(None) |
97 |
|
98 Try(Source.fromURL(my_url)(using "ISO-8859-1").mkString).getOrElse("") |
|
99 |
|
100 Try(Some(Source.fromURL(my_url)(using "ISO-8859-1").mkString)).getOrElse(None) |
69 |
101 |
70 |
102 |
71 // the same for files |
103 // the same for files |
72 |
104 |
73 Try(Some(Source.fromFile("test.txt")("ISO-8859-1").mkString)).getOrElse(None) |
105 Try(Some(Source.fromFile("test.txt")(using "ISO-8859-1").mkString)).getOrElse(None) |
74 |
106 |
75 Try(Source.fromFile("test.txt")("ISO-8859-1").mkString).toOption |
107 Try(Source.fromFile("test.txt")(using "ISO-8859-1").mkString).toOption |
76 |
108 |
77 Using(Source.fromFile("test.txt")("ISO-8859-1"))(_.mkString).toOption |
109 Using(Source.fromFile("test.txt")(using "ISO-8859-1"))(_.mkString).toOption |
78 |
110 |
79 // how to implement a function for reading |
111 // how to implement a function for reading |
80 // (lines) from files... |
112 // (lines) from files... |
81 // |
113 // |
82 def get_contents(name: String) : List[String] = |
114 def get_contents(name: String) : List[String] = |
83 Source.fromFile(name)("ISO-8859-1").getLines().toList |
115 Source.fromFile(name)(using "ISO-8859-1").getLines().toList |
84 |
116 |
85 get_contents("text.txt") |
117 get_contents("text.txt") |
86 get_contents("test.txt") |
118 get_contents("test.txt") |
87 |
119 |
88 // slightly better - return Nil |
120 // slightly better - return Nil |
89 def get_contents(name: String) : List[String] = |
121 def get_contents(name: String) : List[String] = |
90 Try(Source.fromFile(name)("ISO-8859-1").getLines.toList).getOrElse(List()) |
122 Try(Source.fromFile(name)(using "ISO-8859-1").getLines.toList).getOrElse(List()) |
91 |
123 |
92 get_contents("text.txt") |
124 get_contents("text.txt") |
93 |
125 |
94 // much better - you record in the type that things can go wrong |
126 // much better - you record in the type that things can go wrong |
95 def get_contents(name: String) : Option[List[String]] = |
127 def get_contents(name: String) : Option[List[String]] = |
96 Try(Some(Source.fromFile(name)("ISO-8859-1").getLines().toList)).getOrElse(None) |
128 Try(Some(Source.fromFile(name)(using "ISO-8859-1").getLines().toList)).getOrElse(None) |
97 |
129 |
98 get_contents("text.txt") |
130 get_contents("text.txt") |
99 get_contents("test.txt") |
131 get_contents("test.txt") |
100 |
132 |
101 |
133 |
464 |
531 |
465 my_flatten(List(None, Some(1), Some(2), None, Some(3))) |
532 my_flatten(List(None, Some(1), Some(2), None, Some(3))) |
466 |
533 |
467 |
534 |
468 |
535 |
469 |
|
470 |
|
471 |
|
472 |
|
473 |
536 |
474 // Recursion |
537 // Recursion |
475 //=========== |
538 //=========== |
|
539 |
|
540 // my_length |
|
541 |
|
542 def my_length(xs: List[Int]) : Int = { |
|
543 if (xs == Nil) 0 else 1 + my_length(xs.tail) |
|
544 } |
|
545 |
|
546 def my_sum(xs: List[Int]) : Int = { |
|
547 if (xs == Nil) 0 else xs.head + my_sum(xs.tail) |
|
548 } |
|
549 |
|
550 my_sum((1 to 100).toList) |
|
551 my_length(List()) |
|
552 |
|
553 /* my_map */ |
|
554 for (n <- List[Int](1,2,3)) yield n * n |
|
555 |
|
556 List(1,2,3) ::: List(3,4,5) |
|
557 3 :: List(3,4,5) |
|
558 |
|
559 def my_map(xs: List[Int], f : Int => Int ) : List[Int] = { |
|
560 if (xs == Nil) Nil |
|
561 else f(xs.head) :: my_map(xs.tail, f) |
|
562 } |
|
563 |
|
564 def square(n: Int) : Int = n * n |
|
565 |
|
566 |
|
567 my_map(List(1,2,3), square) |
|
568 |
|
569 |
|
570 |
|
571 |
|
572 /* powerset */ |
|
573 |
|
574 def powerset(xs: Set[Int]) : Set[Set[Int]] = { |
|
575 if (xs == Set()) Set(Set()) |
|
576 else powerset(xs.tail) ++ powerset(xs.tail).map(_ + xs.head) |
|
577 } |
|
578 |
|
579 |
|
580 |
|
581 |
|
582 |
|
583 /* on lists */ |
|
584 def powerset(xs: List[Int]) : List[List[Int]] = { |
|
585 if (xs == Nil) List(Nil) |
|
586 else powerset(xs.tail) ::: powerset(xs.tail).map(xs.head :: _) |
|
587 } |
|
588 |
476 |
589 |
477 |
590 |
478 /* Say you have characters a, b, c. |
591 /* Say you have characters a, b, c. |
479 What are all the combinations of a certain length? |
592 What are all the combinations of a certain length? |
480 |
593 |
580 // scala -cp scala-parallel-collections_2.13-0.2.0.jar |
695 // scala -cp scala-parallel-collections_2.13-0.2.0.jar |
581 // import scala.collection.parallel.CollectionConverters._ |
696 // import scala.collection.parallel.CollectionConverters._ |
582 |
697 |
583 |
698 |
584 |
699 |
585 |
700 def powerset(xs: Set[Int]) : Set[Set[Int]] = { |
|
701 if (xs == Set()) Set(Set()) |
|
702 else { |
|
703 val ps = powerset(xs.tail) |
|
704 ps ++ ps.map(_ + xs.head) |
|
705 } |
|
706 } |
|
707 |
|
708 def psubsets(xs: Set[Int]) = |
|
709 powerset(xs) -- Set(Set(), xs) |
|
710 |
|
711 //def psubsets(xs: Set[Int]) = |
|
712 // xs.subsets.toList -- Set(Set(), xs) |
|
713 |
|
714 def splits(xs: Set[Int]) : Set[(Set[Int], Set[Int])] = |
|
715 psubsets(xs).map(s => (s, xs -- s)) |
|
716 |
|
717 |
|
718 |
|
719 enum Tree { |
|
720 case Num(i: Int) |
|
721 case Add(l: Tree, r: Tree) |
|
722 case Sub(l: Tree, r: Tree) |
|
723 case Mul(l: Tree, r: Tree) |
|
724 case Div(l: Tree, r: Tree) |
|
725 } |
|
726 import Tree._ |
|
727 |
|
728 def pp(tr: Tree) : String = tr match { |
|
729 case Num(n) => s"$n" |
|
730 case Add(l, r) => s"(${pp(l)} + ${pp(r)})" |
|
731 case Sub(l, r) => s"(${pp(l)} - ${pp(r)})" |
|
732 case Mul(l, r) => s"(${pp(l)} * ${pp(r)})" |
|
733 case Div(l, r) => s"(${pp(l)} / ${pp(r)})" |
|
734 } |
|
735 |
|
736 def search(nums: Set[Int]) : Set[Tree] = nums.size match { |
|
737 case 0 => Set() |
|
738 case 1 => Set(Num(nums.head)) |
|
739 case 2 => { |
|
740 val l = nums.head |
|
741 val r = nums.tail.head |
|
742 Set(Add(Num(l), Num(r)), |
|
743 Mul(Num(l), Num(r))) |
|
744 ++ Option.when(l <= r)(Sub(Num(r), Num(l))) |
|
745 ++ Option.when(l > r)(Sub(Num(l), Num(r))) |
|
746 ++ Option.when(r > 0 && l % r == 0)(Div(Num(l), Num(r))) |
|
747 ++ Option.when(l > 0 && r % l == 0)(Div(Num(r), Num(l))) |
|
748 } |
|
749 case xs => { |
|
750 val spls = splits(nums) |
|
751 val subtrs = |
|
752 for ((lspls, rspls) <- spls; |
|
753 lt <- search(lspls); |
|
754 rt <- search(rspls)) yield { |
|
755 Set(Add(lt, rt), Sub(lt, rt), |
|
756 Mul(lt, rt), Div(lt, rt)) |
|
757 } |
|
758 subtrs.flatten |
|
759 } |
|
760 } |
|
761 |
|
762 println(search(Set(1,2,3,4)).mkString("\n")) |
|
763 |
|
764 def eval(tr: Tree) : Option[Int] = tr match { |
|
765 case Num(n) => Some(n) |
|
766 case Add(l, r) => |
|
767 for (rl <- eval(l); rr <- eval(r)) yield rl + rr |
|
768 case Mul(l, r) => |
|
769 for (rl <- eval(l); rr <- eval(r)) yield rl * rr |
|
770 case Sub(l, r) => |
|
771 for (rl <- eval(l); rr <- eval(r); |
|
772 if 0 <= rl - rr) yield rl - rr |
|
773 case Div(l, r) => |
|
774 for (rl <- eval(l); rr <- eval(r); |
|
775 if rr > 0 && rl % rr == 0) yield rl / rr |
|
776 } |
|
777 |
|
778 eval(Add(Num(1), Num(2))) |
|
779 eval(Mul(Add(Num(1), Num(2)), Num(4))) |
|
780 eval(Sub(Num(3), Num(2))) |
|
781 eval(Sub(Num(3), Num(6))) |
|
782 eval(Div(Num(6), Num(2))) |
|
783 eval(Div(Num(6), Num(4))) |
|
784 |
|
785 def time_needed[T](n: Int, code: => T) = { |
|
786 val start = System.nanoTime() |
|
787 for (i <- (0 to n)) code |
|
788 val end = System.nanoTime() |
|
789 (end - start) / 1.0e9 |
|
790 } |
|
791 |
|
792 |
|
793 import scala.collection.parallel.CollectionConverters._ |
|
794 |
|
795 def check(xs: Set[Int], target: Int) = |
|
796 search(xs).find(eval(_) == Some(target)) |
|
797 |
|
798 for (sol <- check(Set(50, 5, 4, 9, 10, 8), 560)) { |
|
799 println(s"${pp(sol)} => ${eval(sol)}") |
|
800 } |
|
801 |
|
802 |
|
803 |
|
804 time_needed(1, check(Set(50, 5, 4, 9, 10, 8), 560)) |
|
805 |
|
806 |
|
807 println(check(Set(25, 5, 2, 10, 7, 1), 986).mkString("\n")) |
|
808 |
|
809 for (sol <- check(Set(25, 5, 2, 10, 7, 1), 986)) { |
|
810 println(s"${pp(sol)} => ${eval(sol)}") |
|
811 } |
|
812 |
|
813 for (sol <- check(Set(25, 5, 2, 10, 7, 1), -1)) { |
|
814 println(s"${pp(sol)} => ${eval(sol)}") |
|
815 } |
|
816 |
|
817 for (sol <- check(Set(100, 25, 75, 50, 7, 10), 360)) { |
|
818 println(s"${pp(sol)} => ${eval(sol)}") |
|
819 } |
|
820 time_needed(1, check(Set(100, 25, 75, 50, 7, 10), 360)) |
|
821 |
|
822 |
|
823 |
|
824 time_needed(1, check(Set(25, 5, 2, 10, 7, 1), 986)) |
|
825 time_needed(1, check(Set(25, 5, 2, 10, 7, 1), -1)) |
|
826 |
|
827 |
|
828 def generate(nums: Set[Int]) : Set[(Tree, Int)] = nums.size match { |
|
829 case 0 => Set() |
|
830 case 1 => Set((Num(nums.head), nums.head)) |
|
831 case xs => { |
|
832 val spls = splits(nums) |
|
833 val subtrs = |
|
834 for ((lspls, rspls) <- spls; |
|
835 (lt, ln) <- generate(lspls); |
|
836 (rt, rn) <- generate(rspls)) yield { |
|
837 Set((Add(lt, rt), ln + rn), |
|
838 (Mul(lt, rt), ln * rn)) |
|
839 ++ Option.when(ln <= rn)((Sub(rt, lt), rn - ln)) |
|
840 ++ Option.when(ln > rn)((Sub(lt, rt), ln - rn)) |
|
841 ++ Option.when(rn > 0 && ln % rn == 0)((Div(lt, rt), ln / rn)) |
|
842 ++ Option.when(ln > 0 && rn % ln == 0)((Div(rt, lt), rn / ln)) |
|
843 } |
|
844 subtrs.flatten |
|
845 } |
|
846 } |
|
847 |
|
848 def check2(xs: Set[Int], target: Int) = |
|
849 generate(xs).find(_._2 == target) |
|
850 |
|
851 for ((sol, ev) <- check2(Set(50, 5, 4, 9, 10, 8), 560)) { |
|
852 println(s"${pp(sol)} => ${eval(sol)} / $ev") |
|
853 } |
|
854 |
|
855 time_needed(1, check(Set(50, 5, 4, 9, 10, 8), 560)) |
|
856 time_needed(1, check2(Set(50, 5, 4, 9, 10, 8), 560)) |
|
857 |
|
858 time_needed(1, check(Set(50, 5, 4, 9, 10, 8), -1)) |
|
859 time_needed(1, check2(Set(50, 5, 4, 9, 10, 8), -1)) |
586 |
860 |
587 // Jumping Towers |
861 // Jumping Towers |
588 //================ |
862 //================ |
589 |
863 |
590 |
864 |