Ir para o conteúdo

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