33
3
As you may know it, the factorial of a positive integer n
is the product of all the positive integers which are equal or smaller to n
.
For instance :
6! = 6*5*4*3*2*1 = 720
0! = 1
We will now define a special operation with an irrelevant name like sumFac
:
Given a positive integer n
, sumFac(n)
is the sum of the factorials of the digits.
For instance :
sumFac(132) = 1! + 3! + 2! = 9
Task
Your mission, whether or not you choose to accept it, is to return the sequence (potentially infinite) of the applications of sumFac
to an integer given in input.
Example : 132 -> 132, 9, 362880, 81369, 403927, ...
But that's not all! Indeed, the applications of sumFac
will eventually create a cycle. You must also return this cycle!
If your language has a built in factorial you can use it. I'm not picky about the return type, you just have to return the sequence of sumFac applications and the cycle in a format understandable by a human.
EDIT : To help you visualize better what should the output look like I copied Leaky Nun's just below:
[132, 9, 362880, 81369, 403927, 367953, 368772, 51128, 40444, 97, 367920, 368649, 404670, 5810, 40442, 75, 5160, 842, 40346, 775, 10200, 6, 720, 5043, 151, 122, 5, 120, 4, 24, 26, 722, 5044, 169, 363601, 1454]
You just need to stop the sequence when the cycle is about to start for the second time!
But this is code-golf so the shortest answer in bytes wins!
Leaderboard
Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.
/* Configuration */
var QUESTION_ID = 117583; // Obtain this from the url
// It will be like https://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 68509; // This should be the user ID of the challenge author.
/* App */
var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page;
function answersUrl(index) {
return "https://api.stackexchange.com/2.2/questions/" + QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}
function commentUrl(index, answers) {
return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER;
}
function getAnswers() {
jQuery.ajax({
url: answersUrl(answer_page++),
method: "get",
dataType: "jsonp",
crossDomain: true,
success: function (data) {
answers.push.apply(answers, data.items);
answers_hash = [];
answer_ids = [];
data.items.forEach(function(a) {
a.comments = [];
var id = +a.share_link.match(/\d+/);
answer_ids.push(id);
answers_hash[id] = a;
});
if (!data.has_more) more_answers = false;
comment_page = 1;
getComments();
}
});
}
function getComments() {
jQuery.ajax({
url: commentUrl(comment_page++, answer_ids),
method: "get",
dataType: "jsonp",
crossDomain: true,
success: function (data) {
data.items.forEach(function(c) {
if (c.owner.user_id === OVERRIDE_USER)
answers_hash[c.post_id].comments.push(c);
});
if (data.has_more) getComments();
else if (more_answers) getAnswers();
else process();
}
});
}
getAnswers();
var SCORE_REG = /<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;
var OVERRIDE_REG = /^Override\s*header:\s*/i;
function getAuthorName(a) {
return a.owner.display_name;
}
function process() {
var valid = [];
answers.forEach(function(a) {
var body = a.body;
a.comments.forEach(function(c) {
if(OVERRIDE_REG.test(c.body))
body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>';
});
var match = body.match(SCORE_REG);
if (match)
valid.push({
user: getAuthorName(a),
size: +match[2],
language: match[1],
link: a.share_link,
});
});
valid.sort(function (a, b) {
var aB = a.size,
bB = b.size;
return aB - bB
});
var languages = {};
var place = 1;
var lastSize = null;
var lastPlace = 1;
valid.forEach(function (a) {
if (a.size != lastSize)
lastPlace = place;
lastSize = a.size;
++place;
var answer = jQuery("#answer-template").html();
answer = answer.replace("{{PLACE}}", lastPlace + ".")
.replace("{{NAME}}", a.user)
.replace("{{LANGUAGE}}", a.language)
.replace("{{SIZE}}", a.size)
.replace("{{LINK}}", a.link);
answer = jQuery(answer);
jQuery("#answers").append(answer);
var lang = a.language;
if (/<a/.test(lang)) lang = jQuery(lang).text();
languages[lang] = languages[lang] || {lang: a.language, user: a.user, size: a.size, link: a.link};
});
var langs = [];
for (var lang in languages)
if (languages.hasOwnProperty(lang))
langs.push(languages[lang]);
langs.sort(function (a, b) {
if (a.lang > b.lang) return 1;
if (a.lang < b.lang) return -1;
return 0;
});
for (var i = 0; i < langs.length; ++i)
{
var language = jQuery("#language-template").html();
var lang = langs[i];
language = language.replace("{{LANGUAGE}}", lang.lang)
.replace("{{NAME}}", lang.user)
.replace("{{SIZE}}", lang.size)
.replace("{{LINK}}", lang.link);
language = jQuery(language);
jQuery("#languages").append(language);
}
}
body { text-align: left !important}
#answer-list {
padding: 10px;
width: 290px;
float: left;
}
#language-list {
padding: 10px;
width: 290px;
float: left;
}
table thead {
font-weight: bold;
}
table td {
padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b">
<div id="answer-list">
<h2>Leaderboard</h2>
<table class="answer-list">
<thead>
<tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr>
</thead>
<tbody id="answers">
</tbody>
</table>
</div>
<div id="language-list">
<h2>Winners by Language</h2>
<table class="language-list">
<thead>
<tr><td>Language</td><td>User</td><td>Score</td></tr>
</thead>
<tbody id="languages">
</tbody>
</table>
</div>
<table style="display: none">
<tbody id="answer-template">
<tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
</tbody>
</table>
<table style="display: none">
<tbody id="language-template">
<tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
</tbody>
</table>
Related – Leaky Nun – 2017-04-25T12:47:31.387
Welcome to PPCG! This looks like a nice challenge, BTW. – clismique – 2017-04-25T12:49:35.367
@Qwerp-Derp Thank you very much! I tried to be creative ^^ – None – 2017-04-25T12:51:06.870
@Zgarb Well it's exactly like the output of Leaky Nun. The sequence of the applications and then it shall end just before the beginning of the second cycle. I'll copy his output in the question so everyone can have a clear understanding. Thanks for pointing that out :) – None – 2017-04-25T13:09:19.880
@Antoine
1454
actually maps to169
. Should I just print the cycle or should I print everything from the start? – Leaky Nun – 2017-04-25T13:18:22.100@LeakyNun You need to print everything that comes before the cycle and end the sequence with the cycle. Which is what you did because the next number would indeed be 169 – None – 2017-04-25T13:23:26.770
Related OEIS – mbomb007 – 2017-04-25T15:00:32.730
How important is the output formatting? Can we have the trailing comma, can the values be separated by a space or a newline instead? – 2501 – 2017-04-26T02:11:49.967
Hardcoding the value 169 is cheating? – 2501 – 2017-04-26T03:44:15.073
1@2501 Hardcoding the value is cheating, but concerning the output formatting you can use any separator you want – None – 2017-04-26T08:40:29.887
@Antoine Ok. The constant 169 doesn't help anyway, since some cycles don't contain it. – 2501 – 2017-04-26T08:46:08.100