Skip to content

Commit

Permalink
Merge pull request #1 from pmpknu/p19
Browse files Browse the repository at this point in the history
Add date utility functions, solutions and inline tests to p19
  • Loading branch information
pmpknu authored Oct 29, 2024
2 parents 9a2849f + cd94927 commit d4fed34
Show file tree
Hide file tree
Showing 16 changed files with 212 additions and 0 deletions.
29 changes: 29 additions & 0 deletions p19/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
*.annot
*.cmo
*.cma
*.cmi
*.a
*.o
*.cmx
*.cmxs
*.cmxa

# ocamlbuild working directory
_build/

# ocamlbuild targets
*.byte
*.native

# oasis generated files
setup.data
setup.log

# Merlin configuring file for Vim and Emacs
.merlin

# Dune generated files
*.install

# Local OPAM switch
_opam/
2 changes: 2 additions & 0 deletions p19/.ocamlformat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
profile = janestreet
version = 0.26.2
4 changes: 4 additions & 0 deletions p19/bin/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(executable
(public_name p19)
(name main)
(libraries p19_lib))
1 change: 1 addition & 0 deletions p19/bin/main.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
let () = print_endline "Hello, World!"
6 changes: 6 additions & 0 deletions p19/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(rule
(alias lint)
(action
(progn
(echo "Running zanuda on OCaml files...")
(run bash -c "zanuda lib/*.ml"))))
22 changes: 22 additions & 0 deletions p19/dune-project
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
(lang dune 3.16)

(name p19)

(generate_opam_files true)

(source
(github pmpknu/fp-lab1))

(authors "Dan Gorlyakov")


(license MIT)

; (documentation https://url/to/documentation)

(package
(name p19)
(synopsis "fp lab1")
(description "two tasks for the first lab for fp course at itmo")
(depends ocaml dune)
)
32 changes: 32 additions & 0 deletions p19/lib/date.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
let is_leap year = (year mod 4 = 0 && year mod 100 <> 0) || year mod 400 = 0

let%test "is_leap for leap year 2000" = is_leap 2000 = true
let%test "is_leap for leap year 2020" = is_leap 2020 = true
let%test "is_leap for non-leap year 1900" = is_leap 1900 = false
let%test "is_leap for non-leap year 2023" = is_leap 2023 = false

let days_in_month year month =
match month with
| 1 | 3 | 5 | 7 | 8 | 10 | 12 -> 31
| 4 | 6 | 9 | 11 -> 30
| 2 -> if is_leap year then 29 else 28
| _ -> failwith "Invalid month"
;;

let%test "days_in_month for February in leap year" = days_in_month 2020 2 = 29
let%test "days_in_month for February in non-leap year" = days_in_month 2021 2 = 28
let%test "days_in_month for January" = days_in_month 2021 1 = 31
let%test "days_in_month for April" = days_in_month 2021 4 = 30

let zellers_congruence year month day =
let year, month = if month < 3 then year - 1, month + 12 else year, month in
let k = year mod 100 in
let j = year / 100 in
let f = day + (13 * (month + 1) / 5) + k + (k / 4) + (j / 4) - (2 * j) in
((f mod 7) + 7) mod 7
;;

let%test "zellers_congruence for 1 Jan 1900 (Monday)" = zellers_congruence 1900 1 1 = 2
let%test "zellers_congruence for 1 Jan 2000 (Saturday)" = zellers_congruence 2000 1 1 = 0
let%test "zellers_congruence for 1 Mar 2021 (Monday)" = zellers_congruence 2021 2 28 = 1
let%test "zellers_congruence for 31 Dec 1999 (Friday)" = zellers_congruence 1999 12 31 = 6
2 changes: 2 additions & 0 deletions p19/lib/date.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
val days_in_month : int -> int -> int
val zellers_congruence : int -> int -> int -> int
7 changes: 7 additions & 0 deletions p19/lib/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(library
(name p19_lib)
(modules date tailrec rec map iterative module)
(inline_tests
(flags (-verbose)))
(preprocess
(pps ppx_inline_test)))
13 changes: 13 additions & 0 deletions p19/lib/iterative.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
open Date

let count_sundays start_year end_year =
let count = ref 0 in
for year = start_year to end_year do
for month = 1 to 12 do
if zellers_congruence year month 1 = 0 then incr count
done
done;
!count
;;

let%test _ = count_sundays 1901 2000 = 171
13 changes: 13 additions & 0 deletions p19/lib/map.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
open Date

let count_sundays start_year end_year =
let years = List.init (end_year - start_year + 1) (fun i -> start_year + i) in
let aux year =
let months = List.init 12 (fun m -> m + 1) in
let map_filter month = if zellers_congruence year month 1 = 0 then 1 else 0 in
List.fold_left ( + ) 0 (List.map map_filter months)
in
List.fold_left (fun acc year -> acc + aux year) 0 years
;;

let%test _ = count_sundays 1901 2000 = 171
12 changes: 12 additions & 0 deletions p19/lib/module.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
open Date

let count_sundays start_year end_year =
let years = List.init (end_year - start_year + 1) (fun i -> start_year + i) in
let aux year =
let months = List.init 12 (fun m -> m + 1) in
List.filter (fun month -> zellers_congruence year month 1 = 0) months |> List.length
in
List.fold_left (fun acc year -> acc + aux year) 0 years
;;

let%test _ = count_sundays 1901 2000 = 171
15 changes: 15 additions & 0 deletions p19/lib/rec.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
open Date

let rec count_sundays year month day_of_week =
if year > 2000
then 0
else (
let new_count = if day_of_week = 0 then 1 else 0 in
let days_this_month = days_in_month year month in
let next_day_of_week = (day_of_week + days_this_month) mod 7 in
if month == 12
then new_count + count_sundays (year + 1) 1 next_day_of_week
else new_count + count_sundays year (month + 1) next_day_of_week)
;;

let%test _ = count_sundays 1901 1 2 = 171
15 changes: 15 additions & 0 deletions p19/lib/tailrec.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
open Date

let rec count_sundays year month day_of_week count =
if year > 2000
then count
else (
let new_count = if day_of_week = 0 then count + 1 else count in
let days_this_month = days_in_month year month in
let next_day_of_week = (day_of_week + days_this_month) mod 7 in
if month == 12
then count_sundays (year + 1) 1 next_day_of_week new_count
else count_sundays year (month + 1) next_day_of_week new_count)
;;

let%test _ = count_sundays 1901 1 2 0 = 171
28 changes: 28 additions & 0 deletions p19/p19.opam
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
synopsis: "fp lab1"
description: "two tasks for the first lab for fp course at itmo"
authors: ["Dan Gorlyakov"]
license: "MIT"
homepage: "https://github.com/pmpknu/fp-lab1"
bug-reports: "https://github.com/pmpknu/fp-lab1/issues"
depends: [
"ocaml"
"dune" {>= "3.16"}
"odoc" {with-doc}
]
build: [
["dune" "subst"] {dev}
[
"dune"
"build"
"-p"
name
"-j"
jobs
"@install"
"@runtest" {with-test}
"@doc" {with-doc}
]
]
dev-repo: "git+https://github.com/pmpknu/fp-lab1.git"
11 changes: 11 additions & 0 deletions p19/solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from datetime import datetime, timedelta

sundays_count = 0

for year in range(1901, 2001):
for month in range(1, 13):
first_day = datetime(year, month, 1)
if first_day.weekday() == 6:
sundays_count += 1

print(sundays_count)

0 comments on commit d4fed34

Please sign in to comment.