{"id":1860,"date":"2026-05-30T17:07:38","date_gmt":"2026-05-30T15:07:38","guid":{"rendered":"https:\/\/intsight.com\/?p=1860"},"modified":"2026-05-30T17:09:51","modified_gmt":"2026-05-30T15:09:51","slug":"la-constante-de-kaprekar","status":"publish","type":"post","link":"https:\/\/intsight.com\/index.php\/2026\/05\/30\/la-constante-de-kaprekar\/","title":{"rendered":"La constante de Kaprekar"},"content":{"rendered":"<p><span style=\"font-variant:small-caps;font-size:107%\">Vamos a jugar un poco con<\/span> Austra, para ver hasta d\u00f3nde nos deja llegar. Comencemos por definir un n\u00famero, que supondremos que tiene cuatro d\u00edgitos, y vamos a crear un vector de enteros con esos cuatro d\u00edgitos:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\nlet x=4123, v = [int:x\/1000%10, x\/100%10, x\/10%10, x%10] in\n    v;\n<\/pre>\n<p>Ahora vamos a ordenar esos d\u00edgitos, primero de mayor a menor, y luego, en sentido contrario:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\nlet x=4123, v = [int:x\/1000%10, x\/100%10, x\/10%10, x%10];\nv.sortDesc; v.sort;\n<\/pre>\n<p>Mi intenci\u00f3n, no obstante, es recomponer las dos listas de d\u00edgitos y restar el n\u00famero mayor del menor:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\nlet x=4123, v = [int:x\/1000%10, x\/100%10, x\/10%10, x%10] in\n    polyeval(10, v.sortDesc) - polyeval(10, v.sort);\n<\/pre>\n<p>Cuando el n\u00famero inicial es 4123, la respuesta es 3087. Para hacer las cosas f\u00e1ciles, vamos a definir ahora una funci\u00f3n que reciba un entero y lo transforme de acuerdo con este procedimiento:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\nlet kt(x: int): int = \n  let v = [int:x\/1000%10, x\/100%10, x\/10%10, x%10] in\n    (polyeval(10, v.sortDesc) - polyeval(10, v.sort)).toInt in\n      kt(4123);\n<\/pre>\n<p>He llamado <em>kt<\/em> a la funci\u00f3n: <em><a href=\"https:\/\/en.wikipedia.org\/wiki\/D._R._Kaprekar\" target=\"_blank\">Kaprekar<\/a>&#8216;s transform<\/em>.<br \/>\nAhora quiero aplicar esta funci\u00f3n sucesivamente al resultado de la propia funci\u00f3n. La forma m\u00e1s sencilla de hacerlo en Austra es usar el m\u00e9todo de clase <em>unfold<\/em> de las secuencias de enteros:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\nlet ks(n: int) =\n  let kt(x: int): int = \n    let v = [int:x\/1000%10, x\/100%10, x\/10%10, x%10] in\n      (polyeval(10, v.sortDesc) - polyeval(10, v.sort)).toInt in\n        iseq::unfold(100, n, n => kt(n)) in\n          ks(4123)\n<\/pre>\n<p>Para evitar sustos, he limitado el n\u00famero de elementos en la secuencia generada a 100. En realidad, nos sobran elementos, porque si ejecutamos lo anterior obtendremos:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\n4,123  3,087  8,352  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174\n6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174\n6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174\n6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174\n6,174  6,174  6,174  6,174  6,174  6,174  6,174  6,174  \n<\/pre>\n<p>Como se ve, a la tercera aplicaci\u00f3n de la funci\u00f3n de transformaci\u00f3n, la secuencia produce el n\u00famero 6174, que tiene la curiosa propiedad <em>kt(6174)=6174<\/em>. A este n\u00famero, comprensiblemente, se le conoce como <em>constante de Kaprekar<\/em>. Este es un ejemplo de <em>punto fijo<\/em> de una funci\u00f3n, que en este caso es la transformaci\u00f3n de Kaprekar.<br \/>\nPara embellecer un poco el resultado, vamos a intentar parar la secuencia cuando se empiecen a repetir valores. A la secuencia que generamos antes, vamos a aplicarle la propiedad <em>fixedPoint<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\nlet ks(n: int) =\n  let kt(x: int): int = \n    let v = [int:x\/1000%10, x\/100%10, x\/10%10, x%10] in\n      (polyeval(10, v.sortDesc) - polyeval(10, v.sort)).toInt in\n        iseq::unfold(100, n, n => kt(n)).fixedPoint in\n          ks(4123)\n<\/pre>\n<p>Con este peque\u00f1o cambio, la secuencia ahora es m\u00e1s clara:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\n4,123  3,087  8,352  6,174\n<\/pre>\n<p>Si, en vez de utilizar 4123 como semilla, usamos 7773, digamos, obtenemos una secuencia parecida, que tambi\u00e9n converge en 6174:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\n7,773  3,996  6,264  4,176  6,174\n<\/pre>\n<p>Esta vez hemos necesitado cuatro pasos para tropezar con la constante de Kaprekar. \u00bfCu\u00e1l es el n\u00famero m\u00e1ximo de pasos para que una secuencia creada a partir de un n\u00famero arbitrario de cuatro d\u00edgitos converja en la constante de Kaprekar? Para calcularlo, s\u00f3lo necesitamos a\u00f1adir un paso m\u00e1s: una <a href=\"https:\/\/intsight.com\/index.php\/2023\/12\/18\/list-comprehensions-in-austra\/\">comprensi\u00f3n de listas<\/a>.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\nlet ks(n: int) =\n  let kt(x: int): int = \n    let v = [int:x\/1000%10, x\/100%10, x\/10%10, x%10] in\n      (polyeval(10, v.sortDesc) - polyeval(10, v.sort)).toInt in\n        iseq::unfold(100, n, n => kt(n)).fixedPoint in\n          [x <- 1000..9999 => ks(x).length].max\n<\/pre>\n<p>La respuesta es ocho. La cota inicial m\u00e1xima de 100 pasos es m\u00e1s que suficiente, pero como las secuencias de Austra se calculan por demanda, no hace da\u00f1o al tiempo de ejecuci\u00f3n del algoritmo.<br \/>\n\u00bfPara qu\u00e9 sirve todo esto? El punto fijo es un concepto muy importante en matem\u00e1ticas. No voy a enumerar aqu\u00ed las aplicaciones del concepto. Pero podemos quedar en que la constante de Kaprekar nos ha servido de excusa para probar si el lenguaje funcional de Austra es suficientemente potente. Para el ejemplo, he decidido crear una expresi\u00f3n enorme y relativamente complicada, pero tambi\u00e9n podr\u00edamos haberlo conseguido definiendo las funciones <em>kt<\/em> y <em>ks<\/em> por separado. Cuesti\u00f3n de gustos&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Vamos a jugar un poco con Austra, para ver hasta d\u00f3nde nos deja llegar. Comencemos por definir un n\u00famero, que supondremos que tiene cuatro d\u00edgitos, y vamos a crear un vector de enteros con esos cuatro d\u00edgitos: let x=4123, v = [int:x\/1000%10, x\/100%10, x\/10%10, x%10] in v; Ahora vamos a ordenar esos d\u00edgitos, primero de [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1861,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[92],"tags":[124,123],"class_list":["post-1860","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-austra","tag-fixed-point","tag-kaprekar"],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/intsight.com\/wp-content\/uploads\/2026\/05\/fixedPoint-e1780151344747.jpg?fit=500%2C500&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts\/1860","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/comments?post=1860"}],"version-history":[{"count":7,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts\/1860\/revisions"}],"predecessor-version":[{"id":1869,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts\/1860\/revisions\/1869"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/media\/1861"}],"wp:attachment":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/media?parent=1860"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/categories?post=1860"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/tags?post=1860"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}