Determinar dia-da-semana
; Exercicio 9 - Dia-da-semana
;
; Exercício resolvido por: Rui Maia (deathseeker25@portugal-a-programar.org)
;
; Quer saber em que dia da semana ocorreu o 25 de Abril de 1974? Ou em que dia da semana nasceu,
; sem perguntar aos seus pais?
;
; Para determinar o dia da semana de uma data do calendário, utiliza-se um algoritmo que agora se descreve.
; Mas antes disso:
;
; m -> mês do ano em que Março é o mês 1, Abril é o 2, até Dezembro que é o mês 10. Janeiro e Fevereiro
;são considerados os meses 11 e 12 do ano anterior (esta identificacao dos meses, perfeitamente anormal
;é utilizada apenas neste algoritmo).
; d -> dia do mês
; a -> ano do século
; s -> século anterior (mais uma identificacao anormal, para utilizador no algoritmo)
;
; Por exemplo, para 4 de Julho de 1989 será m=5, d=4, a=89, s=19. Por outro lado, para 4 de Janeiro do mesmo ano
;será m=11, d=4, a=88, s=19.
;
; Vejamos agora os passos do algoritmo. Seja:
;
; mint = parte inteira de (13*m-1)/5
; aint = parte inteira de a/4
; sint = parte inteira de s/4
; x = mint + aint + sint + d + a-2*s
; dia = resto da divisao inteira x/7
;
; dia é a resposta, de acordo com a identificacao seguinte: dia=0 é o Domingo, dia=1 é segunda-feira, e assim
;sucessivamente até dia=6 que corresponde a Sábado.
;
; Escreva em Scheme o programa dia-da-semana que, em relacao a uma data, pede o dia, mês e ano e responde com o
;respectivo dia da semana. Na chamada que se segue, a data em causa é 18 de Agosto de 2001.
;
;>(dia-da-semana)
;dia : 18
;mes: 8
;ano: 2001
;dia da semana: 6
;
(define atribui-dia
(lambda (d m a s)
(let ((mint (quotient (- (* 13 m) 1) 5))
(aint (quotient a 4))
(sint (quotient s 4)))
(+ mint aint sint d (- a (* 2 s))))))
(define calcula-dia
(lambda (x)
(remainder x 7)))
(define atribui-ano-consoante-o-mes
(lambda (mes ano)
(cond ((or (= mes 11) (= mes 12))
(sub1 (remainder ano 100)))
(else
(remainder ano 100)))))
(define atribui-mes
(lambda (mes)
(cond ((= mes 1)
11)
((= mes 2)
12)
((= mes 3)
1)
((= mes 4)
2)
((= mes 5)
3)
((= mes 6)
4)
((= mes 7)
5)
((= mes 8)
6)
((= mes 9)
7)
((= mes 10)
8)
((= mes 11)
9)
((= mes 12)
10))))
(define dia-da-semana
(lambda ()
(display "dia: ")
(let ((dia (read)))
(display "mes: ")
(let ((mes (read)))
(display "ano: ")
(let ((ano (read)))
(display "dia da semana: ")
(let ((m (atribui-mes mes))
(d dia)
(a (atribui-ano-consoante-o-mes (atribui-mes mes) ano)) ; o comando remainder da o resto de uma divisao..
(s (quotient ano 100)))
(if (< (calcula-dia(atribui-dia d m a s)) 0) ; se o resultado for menor do que zero
(+ 7 (calcula-dia (atribui-dia d m a s))) ; faz-se 7 + resultado, ja que o resultado e negativo
(calcula-dia(atribui-dia d m a s))))))))) ; caso nao seja, faz-se apenas o calcula-dia...
;> (dia-da-semana)
;dia: 18
;mes: 8
;ano: 2001
;dia da semana: 6
;> (dia-da-semana)
;dia: 25
;mes: 4
;ano: 1974
;dia da semana: 4
;> (dia-da-semana)
;dia: 16
;mes: 6
;ano: 1989
;dia da semana: 5
;> (dia-da-semana)
;dia: 16
;mes: 6
;ano: 2007
;dia da semana: 6
;> (dia-da-semana)
;dia: 2
;mes: 12
;ano: 2007
;dia da semana: 0