0votos

Averigua en que piso esta cada numero. en Haskell

por josejuan hace 6 años

Como es de esperar puede calcularse fácilmente de forma directa, es decir, con coste O(1). De hecho, es menos simple la función de test...

Modo de realizar libre.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
{-- 
  Dado un nº devuelve el piso en el que está. 
--} 
pisoN :: Int -> Int 
pisoN n = if m >= n && n >= m' then d - n 
          else if n >= m''     then d - m' 
          else if n > m'''     then n - d' 
                               else d - m 
          where c = ceiling (((sqrt.fromIntegral) n + 1) * 0.5) -- El cuadrado en que está: 1, 2.. 
                l = 2 * c - 1                                   -- El lado del cuadrado en que está. 
                m = l * l                                       -- El mayor nº del cuadrado en que está. 
                m' = m - l + 1                                  -- Menor nº de la columna derecha. 
                d = (l - 1) `div` 2 + m'                        -- Delta de ajuste derecho (..-2, -1, 0, 1, 2..) 
                m'' = m' - l + 1                                -- Menor nº de la fila superior. 
                m''' = m'' - l + 1                              -- Menor nº de la columna izquierda. 
                d' = (l - 1) `div` 2 + m'''                     -- Delta de ajuste izquierdo (..-2, -1, 0, 1, 2..) 
 
-- (ver test abajo) 
 
 
 
 
 
 
 
 
 
 
 
{-- 
 
  Para testear la función anterior, podemos generar los infinitos nºs en serie 
  calculando el piso. 
 
  Realmente es más complicado generar la secuencia en base a un estado previo 
  que calcularlo directamente (con la función "pisoN") ¡pero hay que testearla! 
 
--} 
 
 
 
 
{-- 
  Dado el nº, piso y lado del cuadrado en el que se encuentra su celda inf-der, 
  genera la infinita lista de nºs y el piso en el que están. 
--} 
generarPisos :: Int -> Int -> Int -> [(Int, Int)] 
generarPisos n0 p l0 = s1 ++ s2 ++ s3 ++ s4 ++ generarPisos nid pi l 
  where s1 = map     (\n -> (n, pi)) $ take (l - 1) [n, n + 1..] 
        s3 = map     (\n -> (n, ps)) $ take (l - 1) [nsi, nsi + 1..] 
        s2 = zipWith (\i n -> (n, pi + i)) [1..l - 1] [nii, nii + 1..] 
        s4 = zipWith (\i n -> (n, ps - i)) [1..l - 1] [nsd, nsd + 1..] 
 
        n = n0 + 1              -- Menor nº de nuestro cuadrado 
        l = l0 + 2              -- Lado de nuestro cuadrado 
 
        nii = n   + l - 1       -- El nº siguiente de la esquina inf-izq         
        nsi = nii + l - 1       -- El nº siguiente de la esquina sup-izq         
        nsd = nsi + l - 1       -- El nº siguiente de la esquina sup-der         
        nid = nsd + l - 2       -- El nº de la esquina inf-der 
 
        pi = p - 1              -- Planta inferior 
        ps = p + l - 2          -- Planta superior 
 
todosPisos :: [(Int, Int)] 
todosPisos = generarPisos 1 0 1 
 
{-- 
 
  Buscamos discrepancias para los primero N nºs 
 
--} 
erroresPiso maxN = filter esError $ take maxN $ todosPisos 
  where esError (n, p) = pisoN n /= p 
 
 
{-- 
  Testeando hasta n = 10^6 todo es correcto: 
 
  *Main> erroresPiso 1000000 
  [] 
 
--} 
2 comentarios
0votos

Escrito por ebrasca hace 6 años

1 Me alegra que ayas dado una respuesta para mi primera kata propuesta.
2 Haskell para mi es incomprensible (me pase mucho tiempo intentando entenderlo)
3 Se me recordó que este ejercicio lo hice en la segunda etapa las olimpiadas matemáticas en Madrid,
Si lo encuentro pasare el link de este ejercicio de las olimpiadas.
0votos

Escrito por ebrasca hace 6 años

¿Me podrías decir en que falla mi código?
¿Usas derivadas?

Comenta la solución

Tienes que identificarte para poder publicar tu comentario.