Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vadzimz homework 6 #22

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
dc6a609
Update homework.clj
Vadzimz Nov 9, 2023
e06b680
Merge branch 'Clojure-Developer:main' into main
Vadzimz Nov 12, 2023
e225a89
Update homework.clj
Vadzimz Nov 12, 2023
b0f435b
Update palindrome.clj
Vadzimz Nov 12, 2023
c4f2530
Update pangram.clj
Vadzimz Nov 12, 2023
3a0cb24
Update square_code.clj
Vadzimz Nov 17, 2023
df47508
Merge branch 'Clojure-Developer:main' into main
Vadzimz Nov 21, 2023
370d245
Update magic_square.clj
Vadzimz Nov 21, 2023
7db6bbb
Update scramblies.clj
Vadzimz Nov 21, 2023
4d9e168
Merge branch 'Clojure-Developer:main' into main
Vadzimz Nov 22, 2023
87105d3
Update square_code.clj
Vadzimz Nov 22, 2023
20df132
Update magic_square.clj
Vadzimz Nov 22, 2023
51eb7a5
Update scramblies.clj
Vadzimz Nov 22, 2023
ecad7f6
Update magic_square.clj
Vadzimz Nov 22, 2023
aa186a8
Update palindrome.clj
Vadzimz Nov 22, 2023
cb49594
Update pangram.clj
Vadzimz Nov 22, 2023
e99a55b
Update scramblies.clj
Vadzimz Nov 22, 2023
48cbfdb
Update magic_square.clj
Vadzimz Nov 22, 2023
6b44096
Update square_code.clj
Vadzimz Nov 22, 2023
cafbdbc
Update scramblies.clj
Vadzimz Nov 22, 2023
a0fc441
Update square_code.clj
Vadzimz Nov 22, 2023
c896d8e
Update scramblies.clj
Vadzimz Nov 22, 2023
9eb2b5f
Merge branch 'Clojure-Developer:main' into main
Vadzimz Nov 25, 2023
8314db8
Merge branch 'Clojure-Developer:main' into main
Vadzimz Dec 29, 2023
dba3c8a
Vadzimz-homework-6
Vadzimz Dec 29, 2023
6406b00
Merge pull request #1 from Vadzimz/Vadzimz-homework-6
Vadzimz Dec 29, 2023
d260dbe
vadzimz homework 6.clj
Vadzimz Dec 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion otus-01/src/otus/homework.clj
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(ns otus.homework)


(defn solution "Add your solution as fuction body here" [])
(defn solution [] (double (/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5))))) (* 3 (- 6 2) (- 2 7)))))

6 changes: 4 additions & 2 deletions otus-02/src/otus_02/homework/palindrome.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
(ns otus-02.homework.palindrome
(:require [clojure.string :as string]))


(defn is-palindrome [test-string])
(defn is-palindrome [test-string]
(->> test-string string/lower-case
(filter #(Character/isLetter %))
(#(= % (reverse %)))))

10 changes: 7 additions & 3 deletions otus-02/src/otus_02/homework/pangram.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
(ns otus-02.homework.pangram
(:require [clojure.string :as string]))


(defn is-pangram [test-string])

(defn is-pangram [test-string]
(->> test-string string/lower-case
(filter #(Character/isLetter %))
(map int)
(into #{})
count
(= 26)))
35 changes: 29 additions & 6 deletions otus-02/src/otus_02/homework/square_code.clj
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
(ns otus-02.homework.square-code)
(ns otus-02.otus-02.homework.square-code
(:require [clojure.math :as math] [clojure.string :as string]))

;; Реализовать классический метод составления секретных сообщений, называемый `square code`.
;; Выведите закодированную версию полученного текста.
Expand Down Expand Up @@ -48,9 +49,31 @@
"aohghn "
"sseoau "

(defn encode-string [input]
(let [st (->> input string/lower-case
(filter #(Character/isLetter %)))
sqr (math/sqrt (count st))
rnd (math/round sqr)
[x y] (if (= (int (math/ceil sqr)) rnd) [(inc rnd) rnd] [rnd rnd])]
(->> (repeat (inc x) (range (inc y)))
flatten
(map vector (concat st (repeat \space)))
(sort-by second)
(map first)
drop-last
(apply str))))


(defn encode-string [input])


(defn decode-string [input])
(defn decode-string [input]
(let [[x y] (->> (range)
(map #(vector % %))
flatten
(#(map vector % (drop 1 %)))
(drop-while #(< (reduce * %) (count input)))
first)]
(->> (repeat x (range y))
flatten
(map vector (concat input (repeat \space)))
(sort-by second)
(map first)
(apply str)
(string/trim))))
22 changes: 14 additions & 8 deletions otus-04/src/otus_04/homework/magic_square.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@
;; Подсказка: используйте "Siamese method"
;; https://en.wikipedia.org/wiki/Siamese_method

(defn magic-square
"Функция возвращает вектор векторов целых чисел,
описывающий магический квадрат размера n*n,
где n - нечётное натуральное число.

Магический квадрат должен быть заполнен так, что суммы всех вертикалей,
горизонталей и диагоналей длиной в n должны быть одинаковы."
[n]
[[0]])
;; r = 1..n MagSq = n * mod(r' + (r - div(n + 3, 2)), n) + mod(r' + r * 2 - 2, n) + 1
(defn magic-square [n]
{:pre [(odd? n)]}
(let [rng (map inc (range n))
repeat-rng (fn [x] (flatten (repeat n x)))
sum-row-col (fn [x y] (map + (sort (repeat-rng x)) (repeat-rng y)))
f-main (fn [x] (map #(mod % n) (sum-row-col rng x)))
b1 (map #(- % (quot (+ n 3), 2)) rng)
b2 (map #(- (* % 2) 2) rng)]
(->> (map + (map #(* % n) (f-main b1)) (f-main b2))
(map inc)
(partition n)
(map vec)
vec)))
7 changes: 4 additions & 3 deletions otus-04/src/otus_04/homework/scramblies.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
;; Оригинальная задача:
;; https://www.codewars.com/kata/55c04b4cc56a697bb0000048

(defn scramble?
(defn scramble? [letters word]
"Функция возвращает true, если из букв в строке letters
можно составить слово word."
[letters word]
nil)
(let [f-freq (fn [x] (map #(get (frequencies x) % 0) (set word)))
[x y] (map f-freq [letters word])]
(every? true? (map >= x y))))
126 changes: 125 additions & 1 deletion otus-06/src/otus_06/homework.clj
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
(ns otus-06.homework)
(ns otus-06.homework
(:require [clojure.string :as string])
(:require [clojure.java.io :as io])
(:require [clojure.set :as set]))

;; Загрузить данные из трех файлов на диске.
;; Эти данные сформируют вашу базу данных о продажах.
Expand Down Expand Up @@ -94,3 +97,124 @@


;; Файлы находятся в папке otus-06/resources/homework

;; VARS
;;**************************************************

(def files (map #(str "homework/" %) ["cust.txt" "prod.txt" "sales.txt"]))

;; запросы
(def menu "\n*** Sales Menu ***
------------------
1. Display Customer Table
2. Display Product Table
3. Display Sales Table
4. Total Sales for Customer
5. Total Count for Product
6. Exit

Enter an option\n")

(def cust-req "Enter a customer name\n")
(def item-req "Enter an item\n")

;; ключи для чтения и отображения
(def cust-keys [:custID :name :address :phoneNumber])
(def prod-keys [:prodID :itemDescription :unitCost])
(def sales-keys [:salesID :custID :prodID :itemCount])
(def sales-keys-to-show [:salesID :name :itemDescription :itemCount])

(def key-names [cust-keys prod-keys sales-keys])

;; ключи для конвертации и расчета total-sum
(def keys-to-int [:itemCount :prodID :custID :salesID])
(def keys-to-double [:unitCost])
(def keys-to-count-total-sum [:unitCost :itemCount])

;; ключи для агрегации
(def keys-to-cust-aggr [:name :totalCost])
(def keys-to-item-aggr [:itemDescription :itemCount])

;; FUNCTIONS
;;**********************************************************************

(defn read-to-maps
"читаем файл с соответствующими keys в список мап"
[f k]
(let [r (io/reader (io/resource f))]
(->> (line-seq r)
(map #(string/split % #"\|"))
(map #(zipmap k %)))))

(defn update-mult-vals
"преобразуем несколько столбов (keys), например, конвертируем"
[map vals fun]
(reduce #(update-in % [%2] fun) map vals))

(defn add-new-key
"добавляем новый столбец (key), рассчитанный из нескольких существующих"
[map keys name fun]
(assoc map name (reduce fun (vals (select-keys map keys)))))

(defn select-data
"выделяем несколько столбцов и преобразуем каждую строку к виду мапа (ID - данные)"
[keys-to-select key-to-first coll]
(->> coll
(map #(select-keys % keys-to-select))
(map #((fn [x key] (merge {(key x) (dissoc x key)})) % key-to-first))))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Как-то сложновато выглядит. Зачем тут вложенные лямбды? Кажется, что стоит одну (fn [x] ..) оставить.


(defn aggregate
"агрегируем данные aggr-key, группируя по name-key"
[[name-key aggr-key] coll]
(->> coll
(map #(select-keys % [name-key aggr-key]))
(group-by name-key)
(map (fn [[name vals]]
{name-key name
aggr-key (reduce + (map aggr-key vals))}))
(map #((fn [x key] {(key x) (dissoc x key)}) % name-key))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тоже лямбда в лямбде. Достаточно оставить (fn [x] {(name-key x) (dissoc x name-key)})

(reduce merge)))

(defn aggregate-and-filter
"агрегируем и фильтруем результат по запрошенному значению name-key"
[[name-key aggr-key] message coll]
(println message)
(flush)
(let [filter-input (read-line)]
(->> coll
(aggregate [name-key aggr-key])
(#(find % filter-input)))))

(defn print-result
"печатаем либо результат, либо уточняющий запрос"
[x]
(if-not (nil? x)
(run! println x)
(println "Precise your input\n")))


;; собираем все данные в одну таблицу (список мап)
(def full-data (->> (map #(read-to-maps %1 %2) files key-names)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Читать какие-либо файлы при инициализации namespace не стоит, так как это явный побочный эффект. А ведь модуль может быть потенциально использован как библиотека, а не только как самостоятельная программа - в этом случае безусловное чтение файлов будет мешать.

А ещё подобные программы перечитывают файлы при каждом запросе от пользователя, ведь общение с последним происходит в диалоговом режиме, а в процессе диалога данные на диске могут и измениться. Кроме того не стоит обращаться к диску за теми данными, которые пользователю не нужны: как только попросит, тогда и следует нужные файлы читать.

(reduce set/join)
(map (fn [x] (update-mult-vals x keys-to-int #(Integer/parseInt %))))
(map (fn [x] (update-mult-vals x keys-to-double parse-double)))
(map (fn [x] (add-new-key x keys-to-count-total-sum :totalCost *)))))

(defn main
"результирующая функция"
[coll]
(println menu)
(flush)
(let [x (read-line)]
(println (str x "\n"))
(->> (cond
(= x "1") (select-data cust-keys :custID coll)
(= x "2") (select-data prod-keys :prodID coll)
(= x "3") (select-data sales-keys-to-show :salesID coll)
(= x "4") (aggregate-and-filter keys-to-cust-aggr cust-req coll)
(= x "5") (aggregate-and-filter keys-to-item-aggr item-req coll)
(= x "6") ["Good Bye\n"])
Comment on lines +210 to +216
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут стоит case использовать вместо cond.

print-result)
(if (not= x "6") (main coll) nil)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь when напрашивается вместо if


(main full-data)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не стоит использовать имя "main" для именования функций, которые не являются точками входа в программу, то есть не принимают строго аргументы командной строки.

Кроме того, производить какие-то побочные эффекты прямо в теле неймспейса - плохая практика. В данном случае следует объявить точку входа и настроить проект так, чтобы оная (точка входа) получала управление при выполнении команды lein run (нужно настроить :main-is).