{"id":6409,"date":"2021-05-19T06:00:09","date_gmt":"2021-05-19T04:00:09","guid":{"rendered":"http:\/\/www.glc.us.es\/~jalonso\/exercitium\/?p=6409"},"modified":"2021-05-26T10:59:34","modified_gmt":"2021-05-26T08:59:34","slug":"numeros-suma-de-dos-cuadrados","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/numeros-suma-de-dos-cuadrados\/","title":{"rendered":"N\u00fameros suma de dos cuadrados"},"content":{"rendered":"<p>El enunciado del problema 3.3 de la <a href=\"https:\/\/bit.ly\/3nSV8NM\">Fase Local de la Olimpiada Matem\u00e1tica Espa\u00f1ola del 2004<\/a> es<\/p>\n<blockquote><p>\n  Hallad todas las posibles formas de escribir 2003 como suma de dos cuadrados de n\u00fameros enteros positivos.\n<\/p><\/blockquote>\n<p>Definir la sucesi\u00f3n<\/p>\n<pre lang=\"text\">\n   sonSumaDosCuadrados :: [Integer]\n<\/pre>\n<p>cuyos elementos son los n\u00fameros que se pueden expresar como suma de los cuadrados de dos n\u00fameros naturales. Por ejemplo,<\/p>\n<pre lang=\"text\">\n   take 6 sonSumaDosCuadrados      ==  [0,1,2,4,5,8]\n   sonSumaDosCuadrados !! (10^4)   ==  39593\n<\/pre>\n<p>Comprobar con QuickCheck las siguientes propiedades:<\/p>\n<ul>\n<li>La sucesi\u00f3n sonSumaDosCuadrados es infinita.<\/li>\n<li>Los elementos de sonSumaDosCuadrados no son congruentes con 3 m\u00f3dulo 4 (es decir, sus restos al dividirlo por 4 son distintos de 3).<\/li>\n<\/ul>\n<p>Usando sonSumaDosCuadrados, resolver el problema propuesto; es decir, calcular todas las posibles formas de escribir 2003 como suma de dos cuadrados de n\u00fameros enteros positivos.<\/p>\n<h4>Soluciones<\/h4>\n<p>&lt;<\/p>\n<p>pre lang=\u00bbhaskell\u00bb><br \/>\nimport Test.QuickCheck (Property, (==>), quickCheck)<\/p>\n<p>&#8212; 1\u00aa soluci\u00f3n<br \/>\n&#8212; ===========<\/p>\n<p>sonSumaDosCuadrados :: [Integer]<br \/>\nsonSumaDosCuadrados =<br \/>\n  filter esSumaDeDosCuadrados [0..]<\/p>\n<p>&#8212; (esSumaDeDosCuadrados) se verifica si n se puede escribir como la<br \/>\n&#8212; suma de los cuadrados de dos n\u00fameros naturales. Por ejemplo,<br \/>\n&#8212;    esSumaDeDosCuadrados 5  ==  True<br \/>\n&#8212;    esSumaDeDosCuadrados 3  ==  False<br \/>\nesSumaDeDosCuadrados :: Integer -> Bool<br \/>\nesSumaDeDosCuadrados = not . null . descomposicionesSumaDosCuadrados<\/p>\n<p>&#8212; (descomposicionesSumaDosCuadrados n) es la lista de pares de<br \/>\n&#8212; cuadrados de n\u00fameros naturales (con la primera componente menor o<br \/>\n&#8212; igual que la segunda) cuya suma es n. Por ejmplo,<br \/>\n&#8212;    descomposicionesSumaDosCuadrados 3    == []<br \/>\n&#8212;    descomposicionesSumaDosCuadrados 4    == [(0,4)]<br \/>\n&#8212;    descomposicionesSumaDosCuadrados 5    == [(1,4)]<br \/>\n&#8212;    descomposicionesSumaDosCuadrados 25   == [(0,25),(9,16)]<br \/>\n&#8212;    descomposicionesSumaDosCuadrados 325  == [(1,324),(36,289),(100,225)]<br \/>\n&#8212;    descomposicionesSumaDosCuadrados 1105 == [(16,1089),(81,1024),(144,961),(529,576)]<br \/>\ndescomposicionesSumaDosCuadrados :: Integer -> [(Integer,Integer)]<br \/>\ndescomposicionesSumaDosCuadrados n =<br \/>\n  [(a,b) | a &lt;- xs,<br \/>\n           let b = n &#8211; a,<br \/>\n           b <code>elem<\/code> xs,<br \/>\n           a &lt;= b]<br \/>\n  where xs = takeWhile (&lt;= n) cuadrados<\/p>\n<p>&#8212; cuadrados es la lista de los cuadrados. Por ejemplo,<br \/>\n&#8212;    take 10 cuadrados  ==  [0,1,4,9,16,25,36,49,64,81]<br \/>\ncuadrados :: [Integer]<br \/>\ncuadrados = map (^2) [0..]<\/p>\n<p>&#8212; 2\u00aa soluci\u00f3n<br \/>\n&#8212; ===========<\/p>\n<p>sonSumaDosCuadrados2 :: [Integer]<br \/>\nsonSumaDosCuadrados2 =<br \/>\n  filter esSumaDeDosCuadrados2 [0..]<\/p>\n<p>esSumaDeDosCuadrados2 :: Integer -> Bool<br \/>\nesSumaDeDosCuadrados2 = not . null . descomposicionesSumaDosCuadrados2<\/p>\n<p>descomposicionesSumaDosCuadrados2 :: Integer -> [(Integer,Integer)]<br \/>\ndescomposicionesSumaDosCuadrados2 n =<br \/>\n  [(a,b) | a &lt;- ys,<br \/>\n           let b = n &#8211; a,<br \/>\n           b <code>elem<\/code> m : zs]<br \/>\n  where m  = n <code>div<\/code> 2<br \/>\n        xs = takeWhile (&lt;= n) cuadrados<br \/>\n        (ys,zs) = span (&lt;= m) xs<\/p>\n<p>&#8212; 3\u00aa soluci\u00f3n<br \/>\n&#8212; ==========<\/p>\n<p>sonSumaDosCuadrados3 :: [Integer]<br \/>\nsonSumaDosCuadrados3 =<br \/>\n  mezclaTodas [[n^2+k^2 | k &lt;- [n..]] | n &lt;- [0..]]<\/p>\n<p>&#8212; (mezclaTodas xss) es la mezcla ordenada de xss, donde tanto xss como<br \/>\n&#8212; sus elementos son listas infinitas ordenadas. Por ejemplo,<br \/>\n&#8212;    \u03bb> take 10 (mezclaTodas [[n,2<em>n..] | n <- [2..]])\n--    [2,3,4,5,6,7,8,9,10,11]\n--    \u03bb> take 10 (mezclaTodas [[n,2<\/em>n..] | n &lt;- [2,9..]])<br \/>\n&#8212;    [2,4,6,8,9,10,12,14,16,18]<\/p>\n<hr \/>\n<p>mezclaTodas :: Ord a => [[a]] -> [a]<br \/>\nmezclaTodas = foldr1 xmezcla<br \/>\n  where xmezcla (x:xs) ys = x : mezcla xs ys<\/p>\n<p>&#8212; (mezcla xs ys) es la mezcla de las listas infinitas ordenadas xs es<br \/>\n&#8212; ys. Por ejemplo,<br \/>\n&#8212;    take 10 (mezcla [1,3..] [4,8..])  == [1,3,4,5,7,8,9,11,12,13]<br \/>\nmezcla :: Ord a => [a] -> [a] -> [a]<br \/>\nmezcla (x:xs) (y:ys) | x &lt; y  = x : mezcla xs (y:ys)<br \/>\n                     | x == y = x : mezcla xs ys<br \/>\n                     | x > y  = y : mezcla (x:xs) ys<\/p>\n<p>&#8212; Comprobaci\u00f3n de equivalencia<br \/>\n&#8212; ============================<\/p>\n<p>&#8212; La comprobaci\u00f3n es<br \/>\n&#8212;    \u03bb> take 1000 sonSumaDosCuadrados == take 1000 sonSumaDosCuadrados2<br \/>\n&#8212;    True<br \/>\n&#8212;    \u03bb> take 1000 sonSumaDosCuadrados2 == take 1000 sonSumaDosCuadrados3<br \/>\n&#8212;    True<\/p>\n<p>&#8212; Comparaci\u00f3n de eficiencia<br \/>\n&#8212; =========================<\/p>\n<p>&#8212; La comparaci\u00f3n es<br \/>\n&#8212;    \u03bb> sonSumaDosCuadrados !! (5<em>10^3)<br \/>\n&#8212;    18973<br \/>\n&#8212;    (2.29 secs, 266,485,976 bytes)<br \/>\n&#8212;    \u03bb> sonSumaDosCuadrados2 !! (5<\/em>10^3)<br \/>\n&#8212;    18973<br \/>\n&#8212;    (1.01 secs, 473,019,976 bytes)<br \/>\n&#8212;    \u03bb> sonSumaDosCuadrados3 !! (5*10^3)<br \/>\n&#8212;    18973<\/p>\n<h2>&#8212;    (0.17 secs, 103,957,288 bytes)<\/h2>\n<p>&#8212;    \u03bb> sonSumaDosCuadrados2 !! (5<em>10^4)<br \/>\n&#8212;    216090<br \/>\n&#8212;    (78.14 secs, 17,856,157,080 bytes)<br \/>\n&#8212;    \u03bb> sonSumaDosCuadrados3 !! (5<\/em>10^4)<br \/>\n&#8212;    216090<br \/>\n&#8212;    (4.23 secs, 3,325,056,480 bytes)<\/p>\n<p>&#8212; Propiedades<br \/>\n&#8212; ===========<\/p>\n<p>&#8212; La primera propiedad es<br \/>\nprop_infinitud :: Integer -> Bool<br \/>\nprop_infinitud n =<br \/>\n  (not . null) (dropWhile (&lt;= n) sonSumaDosCuadrados3)<\/p>\n<p>&#8212; Su comprobaci\u00f3n es<br \/>\n&#8212;    \u03bb> quickCheck prop_infinitud<br \/>\n&#8212;    +++ OK, passed 100 tests.<\/p>\n<p>&#8212; La segunda propiedad es<br \/>\nprop_modulo4 :: Int -> Property<br \/>\nprop_modulo4 k =<br \/>\n  k >= 0 ==><br \/>\n  (sonSumaDosCuadrados3 !! k) <code>mod<\/code> 4  \/= 3<\/p>\n<p>&#8212; Su comprobaci\u00f3n es<br \/>\n&#8212;    \u03bb> quickCheck prop_modulo4<br \/>\n&#8212;    +++ OK, passed 100 tests.<\/p>\n<p>&#8212; 4\u00aa soluci\u00f3n<br \/>\n&#8212; ===========<\/p>\n<p>&#8212; Basada en la 2\u00aa propiedad.<\/p>\n<p>sonSumaDosCuadrados4 :: [Integer]<br \/>\nsonSumaDosCuadrados4 =<br \/>\n  filter esSumaDeDosCuadrados4 [0..]<\/p>\n<p>esSumaDeDosCuadrados4 :: Integer -> Bool<br \/>\nesSumaDeDosCuadrados4 = not . null . descomposicionesSumaDosCuadrados4<\/p>\n<p>descomposicionesSumaDosCuadrados4 :: Integer -> [(Integer,Integer)]<br \/>\ndescomposicionesSumaDosCuadrados4 n<br \/>\n  | n <code>mod<\/code> 4 == 3 = []<br \/>\n  | otherwise      = [(a,b) | a &lt;- ys,<br \/>\n                              let b = n &#8211; a,<br \/>\n                              b <code>elem<\/code> m : zs]<br \/>\n    where m  = n <code>div<\/code> 2<br \/>\n          xs = takeWhile (&lt;= n) cuadrados<br \/>\n          (ys,zs) = span (&lt;= m) xs<\/p>\n<p>&#8212; Comprobaci\u00f3n de equivalencia<br \/>\n&#8212; ============================<\/p>\n<p>&#8212; La comprobaci\u00f3n es<br \/>\n&#8212;    \u03bb> take 1000 sonSumaDosCuadrados3 == take 1000 sonSumaDosCuadrados4<br \/>\n&#8212;    True<\/p>\n<p>&#8212; Comparaci\u00f3n de eficiencia<br \/>\n&#8212; =========================<\/p>\n<p>&#8212; La comparaci\u00f3n es<br \/>\n&#8212;    \u03bb> sonSumaDosCuadrados2 !! (10^4)<br \/>\n&#8212;    39593<br \/>\n&#8212;    (3.60 secs, 1,413,851,720 bytes)<br \/>\n&#8212;    \u03bb> sonSumaDosCuadrados3 !! (10^4)<br \/>\n&#8212;    39593<br \/>\n&#8212;    (0.42 secs, 284,603,104 bytes)<br \/>\n&#8212;    \u03bb> sonSumaDosCuadrados4 !! (10^4)<br \/>\n&#8212;    39593<br \/>\n&#8212;    (2.58 secs, 1,043,995,480 bytes)<\/p>\n<p>&#8212; C\u00e1lculo para resolver el problema<br \/>\n&#8212; =================================<\/p>\n<p>&#8212; El c\u00e1lculo es<br \/>\n&#8212;    \u03bb> 2003 == head (dropWhile (&lt;2003) sonSumaDosCuadrados3)<br \/>\n&#8212;    False<br \/>\n&#8212; Por tanto, no es posible escribir 2003 como suma de dos cuadrados de<br \/>\n&#8212; n\u00fameros enteros positivos.<\/p>\n<h4>Nuevas soluciones<\/h4>\n<ul>\n<li>En los comentarios se pueden escribir nuevas soluciones.\n<li>El c\u00f3digo se debe escribir entre una l\u00ednea con &#60;pre lang=&quot;haskell&quot;&#62; y otra con &#60;\/pre&#62;\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>El enunciado del problema 3.3 de la Fase Local de la Olimpiada Matem\u00e1tica Espa\u00f1ola del 2004 es Hallad todas las posibles formas de escribir 2003 como suma de dos cuadrados de n\u00fameros enteros positivos. Definir la sucesi\u00f3n sonSumaDosCuadrados :: [Integer] cuyos elementos son los n\u00fameros que se pueden expresar como suma de los cuadrados de&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"footnotes":"","_jetpack_memberships_contains_paid_content":false},"categories":[2],"tags":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/6409"}],"collection":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/comments?post=6409"}],"version-history":[{"count":5,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/6409\/revisions"}],"predecessor-version":[{"id":6486,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/6409\/revisions\/6486"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/media?parent=6409"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/categories?post=6409"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/tags?post=6409"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}