number_in_month exercise (Compare two lists with each other) - smlnj

I have previous asked, but no answer so I will try to rewrite the problem.
I have two lists. first list is dates (int * int * int) list and second list is only months. eg(1,2,3,4,5,6,7,8,9,10,11,12) int list
NOTE: assume any number in month list is not repeated and only 1-12.
I want to check how many dates has the same month as in the list of month.
example: [(87,09,08),(67,08,17),(90,08,23)], [1,5,8] = 2
I know how to recursively compare a list with a number, but i cant figure out how to recursivly compare a list with a list...
fun number_in_months (dates :( int * int * int) list, months : int list)=
if null dates
then 0
else if null months
then 0
else
let
fun dm_notempty (dates : (int * int * int) list, months : int list)=
if (null (tl dates) andalso null (tl months)) andalso (#2 (hd dates) <> hd months)
then 0
else if (null (tl dates) andalso null (tl months)) andalso (#2 (hd dates) = hd months)
then 1
else
let val dates_tl = dm_notempty(tl dates, tl months)
in
if #2(hd dates) = hd months
then dates_tl + 1
else dates_tl + 0
end
in
dm_notempty(dates, months)
end

Break the problem down into smaller problems.
For instance, imagine that you had a function number_in_month that counts the occurrences of a single month.
Then you could write this as
fun number_in_months (dates, []) = 0
| number_in_months (dates, x::xs) = number_in_month(dates, x) + number_in_months(dates, xs)
Now all that remains is that function, which is simpler to write because it only has one list argument, not two.
(Implementing it left as an exercise.)

Related

number_in_month exercise (Tycon Mismatch Error In SML function which tries to build a list)

(* Write a function dates_in_month that takes a list of dates and a month (i.e., an int) and
returns a list holding the dates from the argument list of dates that are in the month.
The returned list should contain dates in the order they were originally given. *)
fun dates_in_months( datelist : (int*int*int) list, month : int) =
if null(tl (datelist))
then if #2(hd (datelist)) = month then #2(hd (datelist)) :: [] else []
else if #2(hd (datelist)) = month
then #2(hd (datelist)) :: number_in_month(tl datelist, month)
else number_in_month(tl datelist, month)
This is the error I get:
hw1.sml:55.22-55.78 Error: operator and operand do not agree [tycon mismatch]
operator domain: int * int list
operand: int * int
in expression:
(fn {2=<pat>,...} => 2) (hd datelist) ::
number_in_month (tl datelist,month)
val it = () : unit
Any help appreciated.
Found the correct way:
fun dates_in_month(datelist : (int*int*int) list, month : int) =
if null(tl (datelist))
then if #2(hd (datelist)) = month
then (hd (datelist)) :: []
else []
else if #2(hd (datelist)) = month
then (hd (datelist)) :: dates_in_month(tl datelist, month)
else dates_in_month(tl datelist, month)
I had several flaws, I was calling the function I copied code over from instead of the function itself + some other syntax issues. In addition, I added just the month element of the date-tuple to the list.

add two numbers represented by linked list in scala

I am new to scala and want to write a code that add two numbers represented by linked list in scala as per the below given example
Input:
First List: 5->6->3 // represents number 365
Second List: 8->4->2 // represents number 248
Output
Resultant list: 3->1->6 // represents number 613
I have implemented a code of mutable singly linked list in scala for adding,updating and inserting elements to linked list. Find my code below
class SinglyLinkedList[A] extends ListADT[A] {
private class Node(var data: A,var next: Node)
private var head: Node = null
def apply(index: Int): A = {
require(index >= 0)
var rover = head
for (i <- 0 until index) rover = rover.next
rover.data
}
def update(index: Int,data: A): Unit = {
require(index >= 0)
var rover = head
for (i <- 0 until index) rover = rover.next
rover.data = data
}
def insert(index: Int,data: A): Unit = {
require(index >= 0)
if(index == 0) {
head = new Node(data, head)
}
else{
var rover = head
for (i <- 0 until index-1)
rover = rover.next
rover.next = new Node(data, rover.next)
}
}
def remove(index: Int): A = {
require(index >= 0)
if(index == 0){
val ret = head.data
head = head.next
ret
} else {
var rover = head
for (i <- 0 until index-1) rover = rover.next
val ret = rover.next.data
rover.next = rover.next.next
ret
}
}
}
Can anyone let me know how I am going to perform the addition of two numbers represented by linked list.
How does addition works? I mean the addition on paper: one number under the other?
Let's try for 465 + 248
465
+ 248
---
We start with the least significant digits: 5 + 8. But 5 + 8 = 13, so the result won't fit into a single digit. Which is why we do just like a teacher in preschool taught us: we leave the unit digit and carry the tens digit to the next column
1
465
+ 248
---
3
Now tens. 6 + 4 + (carried) 1 = 11. Again, we leave 1 and carry 1 to the next column:
11
465
+ 248
---
13
And the last column. 4 + 2 + 1 = 7.
11
465
+ 248
---
713
Thus result is 713. If one these 2 numbers have more column or you would carry in the last addition, you could just rewrite remaining numbers.
With immutable liked list it would work the same way (I'll explain in a moment why I used immutable):
take both lists
take heads of both lists (if one of them is empty, you can just return the other as a result of addition)
add heads, and split the result into carry and current digit (carry would be 0 or 0, digit 0 to 9)
if there is carry > 0 add list carry :: Nil to one of tails recursively
prepend digit to recursively added tails
You should end up with something like that:
val add: (List[Int], List[Int]) => List[Int] = {
case (a :: as, b :: bs) =>
val digit = (a + b) % 10
val carry = (a + b) / 10
if (carry > 0) digit :: add(add(as, carry :: Nil), bs)
else digit :: add(as, bs)
case (as, Nil) => as
case (Nil, bs) => bs
}
add(5 :: 6 :: 4 :: Nil, 8 :: 4 :: 2 :: Nil) // 3 :: 1 :: 7 :: Nil
Now, if you would use mutable list it would get trickier. If you want to use mutable list you want to update one of them, right? Which one - first? Second? Both? Your algorithm might calculate the right result but butcher the input.
Let's say you always add the second list to the fist one, and you want to leave the second intact. If the second list is longer, and you would have to add some new places for digits, you have to copy all remaining segments (otherwise you could e.g. update one number in second list and change the first one). You would also have to handle the corner case with carry.
Quite counter-intuitive behavior - numbers are not mutable, and you want to represent numbers.
Try this:
def add(a: List[Int], b: List[Int], o: Int): List[Int] = (a,b,o) match {
case (x::xs, y::ys, d) =>
val v = d + x + y
(v%10)::add(xs, ys, v/10)
case (Nil, Nil, 0) => Nil
case (Nil, Nil, d) => d::Nil
case (xs, Nil, d) => add(xs, 0::Nil, d)
case (Nil, ys, d) => add(0::Nil, ys, d)
}

Getting the date of the next day in PureScript

Is there anyway to write the following function more elegantly?
I can see some patterns but I'm not sure how to abstract them or how to find a simpler way to write the function.
type HasRemainder = Boolean
tomorrow :: Date -> Date
tomorrow date = unsafePartial $ canonicalDate y (fst m) (fst d)
where d :: Tuple Day HasRemainder
d = case toEnum $ 1 + fromEnum (day date) of
Just v -> Tuple v false
Nothing -> Tuple (unsafePartial $ fromJust $ toEnum 1) true
m :: Tuple Month HasRemainder
m = if snd d then
case toEnum $ 1 + fromEnum (month date) of
Just v -> Tuple v false
Nothing -> Tuple (unsafePartial $ fromJust $ toEnum 1) true
else Tuple (month date) false
y :: Year
y = if snd m then
case toEnum $ 1 + fromEnum (year date) of
Just v -> v
-- use 2018 arbitrarly if the conversion from int to Date fails
Nothing -> unsafePartial $ fromJust $ toEnum 2018
else (year date)
I'd do something like this:
import Data.DateTime as DT
import Data.Maybe (maybe)
import Data.Time.Duration (Days(..))
tomorrow :: DT.Date -> DT.Date
tomorrow dt = maybe dt DT.date $ DT.adjust (Days 1.0) (DT.DateTime dt bottom)
Although it will return the input date in the unlikely event that the given date is top (which is 31st December 275759 if I remember correctly).
There is an adjust function for Time and DateTime so it's just an oversight that Date is missing one.
I would try something along those lines
getDatePart datepart defaultval1 defaultval2 =
case toEnum $ defaultval1 + fromEnum datepart of
Just v -> Tuple v false
Nothing -> Tuple (unsafePartial $ fromJust $ toEnum defaultval2) true
getDatePartDefault d datepart defaultval1 defaultval2 =
if snd d then
getDatePart datepart defaultval1 defaultval2
else Tuple datepart false
tomorrow :: Date -> Date
tomorrow date = unsafePartial $ canonicalDate (fst y) (fst m) (fst d)
where d :: Tuple Day HasRemainder
d = getDatePart (day date) 1 1
m :: Tuple Month HasRemainder
m = getDatePartDefault d (month date) 1 1
y :: Tuple Year HasRemainder
y = getDatePartDefault d (year date) 1 2018
Take care: this is not tested
Using succ from Enum:
import Data.Date (Date)
import Data.Enum (succ)
import Data.Maybe (Maybe)
today :: Date
today = ...
tomorrow :: Maybe Date
tomorrow = succ today

Scala : How to check every single digit of a number is even or odd?

def digitaleven(n:Int):Boolean = {
if (n%2==0){
return true
}
else {
return false
}
}
this is what i got so far but it only works for single digit number, how do i make it work for a number which has random digits using recursion (if else)?
f.e.: i know how to check every digit for even or odd, n%2 for last digit, n/10%2 for secound last and so on... but i have difficulties to implement it
thanks for helping
forall
Use forall to check if every digit is even (You need not use map to transform. Do transformation inside forall).
def isAllEven(n: Int) = s"$n".forall(_.asDigit % 2 == 0)
Recursive (tail recursive)
def isAllEven(n: Int): Boolean = {
val digits = s"$n".toList
def helper(rest: List[Char]): Boolean = rest match {
case Nil => true
case x :: xs =>
if (x.asDigit % 2 == 0)
helper(xs)
else false
}
helper(digits)
}
The above function converts the number into its string representation and then converts the string to list of chars and then check if each char is even digit.
Your code can be written like below but it will not check if each digit is even.
def digitaleven(n:Int): Boolean = n % 2 == 0
Your code checks if the number is even or not. But it will not check if each digit in the number is even. In order to do that use above recursive function.
A one-liner.
def digitaleven(n:Int):Boolean =
n == 0 || n % 2 == 0 && digitaleven(n/10)
What about this:
def allDigitsEven(number:Int) = {
number.toString.map(_.asDigit).forall(_%2==0)
}
First you need to identify the base case for which you are sure that all the digits are even and return true. Then if you're not sure about all digits but the current digit is even you enter the recursive case to check that all other digits are also even.
It's perfectly possible using only those formulas of yours.
Another way:
// Using explicit recursion and pattern matching
def digitaleven(n:Int):Boolean = n match {
case 0 => true
case n => ((n % 10) % 2 ==0) && digitaleven(n / 10)
}

Is there a Scala-way to get the length of a number?

I would like to know, if there is a Scala built-in method to get the length of the decimal representation of an integer ?
Example: 45 has length 2; 10321 has length 5.
One could get the length with 10321.toString.length, but this smells a bit because of the overhead when creating a String object. Is there a nicer way or a built-in method ?
UPDATE:
With 'nicer' I mean a faster solution
I am only interested in positive integers
This is definitely personal preference, but I think the logarithm method looks nicer without a branch. For positive values only, the abs can be omitted of course.
def digits(x: Int) = {
import math._
ceil(log(abs(x)+1)/log(10)).toInt
}
toString then get length of int will not work for negative integers. This code will work not only for positive numbers but also negatives.
def digits(n:Int) = if (n==0) 1 else math.log10(math.abs(n)).toInt + 1;
If you want speed then something like the following is pretty good, assuming random distribution:
def lengthBase10(x: Int) =
if (x >= 1000000000) 10
else if (x >= 100000000) 9
else if (x >= 10000000) 8
else if (x >= 1000000) 7
else if (x >= 100000) 6
else if (x >= 10000) 5
else if (x >= 1000) 4
else if (x >= 100) 3
else if (x >= 10) 2
else 1
Calculating logarithms to double precision isn't efficient if all you want is the floor.
The conventional recursive way would be:
def len(x: Int, i: Int = 1): Int =
if (x < 10) i
else len(x / 10, i + 1)
which is faster than taking logs for integers in the range 0 to 10e8.
lengthBase10 above is about 4x faster than everything else though.
Something like this should do the job:
def numericLength(n: Int): Int = BigDecimal(n).precision
Take log to the base 10, take the floor and add 1.
The easiest way is:
def numberLength(i : Int): Int = i.toString.length
You might add a guarding-condition because negative Int will have the length of their abs + 1.
Another possibility can be:
private lazy val lengthList = (1 until 19).map(i => i -> math.pow(10, i).toLong)
def numberSize(x: Long): Int =
if (x >= 0) positiveNumberSize(x)
else positiveNumberSize(-x) + 1
private def positiveNumberSize(x: Long): Int =
lengthList
.collectFirst {
case (l, p) if x < p => l
}
.getOrElse(19)
Most people gave the most efficient answer of (int) log(number)+1
But I want to get a bit deeper into understanding why this works.
Let N be a 3 digit number. This means N can be any number between 100 and 1000, or :
100 < N < 1000
=> 10^2 < N < 10^3
The Logarithmic function is continuous , therefore :
log(10^2) < log(N) < log(10^3)
=> 2 < log(N) < 3
We can conclude that N's logarithm is a number between 2 and 3 , or in other words , any 3 digit numbers' logarithm is between 2 and 3.
So if we take only the integer part of a numbers logarithm(eg. the integer part of 2.567 is 2) and add 1 we get the digit length of the number.
Here is the solution:
number.toString.toCharArray.size
input - output
45 - 2
100 - 3