I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

Talk:Two identical strings

From Rosetta Code

task title[edit]

This (draft) task needs a better name,   perhaps:

       Decimal numbers whose binary version can be expressed as a concatenation of two identical binary literals.

Wordy and a bit verbose,   but more accurate.     -- Gerard Schildberger (talk) 10:04, 3 April 2021 (UTC)

task clarification[edit]

Obviously, 10 bits goes to 1024, and that's just over the limit of 1000. In the examples so far, "half" binary string literals are 1 to 5 digits long, each starting with one:

1
10, 11
100, 110, 101, 111
etc...

Doubling to:

11
1010, 1111
100100, 110110, 101101, 111111
etc...

Will it be permitted to do leading zeros on the "half" binary literals? Such as:

001, 010, 011, etc...
0001, 0010, 0011, etc...
00001, 00010, 00011, etc...

Doubling to:

001001, 010010, 011011, etc...
00010001, 00100010, 00110011, etc...
0000100001, 0001000010, 0001100011, etc...

And of course, are palindromes permitted?

example: 1001111001, 1100110011, etc..., and the like.

The two "halves" are still identical, just reversed.--Enter your username (talk) 10:55, 3 April 2021 (UTC)

Here is an example program to count the different ways:

using System; using static System.Console; using System.Collections.Generic;
class Program {
static void fun(bool anylead, bool palin, bool verbose = false) {
var res = new List<int>();
string s = "01", t;
for (int a = 0; a < 2; a++)
for (int b = 0; b < 2; b++)
for (int c = 0; c < 2; c++)
for (int d = 0; d < 2; d++)
for (int e = 0; e < 2; e++) {
t = "" + s[a] + s[b] + s[c] + s[d] + s[e];
for (int i = 0; i < 5; i++) {
int x = Convert.ToInt32("" + t + t, 2);
if (t[0] == '1' || anylead) if (!res.Contains(x) && x < 1000) { if (verbose) { Write("{0} ", "" + t + t); Write("({0}) ", x); } res.Add(x); }
if (palin) {
string tt = t; for (int j = t.Length - 1; j >= 0; j--) tt += t[j];
x = Convert.ToInt32(tt, 2); if (!res.Contains(x) && x < 1000) { if (verbose) {Write("{0} ", tt); Write("({0}) ", x); } res.Add(x); }
}
t = t.Substring(1);
}
}
if (verbose) WriteLine();
Write(". {0,20}, {1,5} palindromes: ", anylead ? "any leading digit" : "only starts with '1'", palin ? "allow" : "no");
WriteLine(res.Count); res.Sort(); if (verbose) WriteLine(string.Join(" ", res));
}
 
static void Main(string[] args) {
fun(true, true);
fun(!true, true);
fun(true, !true);
fun(!true, !true);
}
}
Output:
.    any leading digit, allow palindromes: 91
. only starts with '1', allow palindromes: 76
.    any leading digit,    no palindromes: 57
. only starts with '1',    no palindromes: 30
--Enter your username (talk) 11:41, 3 April 2021 (UTC)

FreeBASIC black magic[edit]

The FreeBASIC solution to this task is super neat! Any chance for an explanation as to how/why it works? --Chunes (talk) 12:48, 3 April 2021 (UTC)

log n/log 2 is the number of bits - 1 representing n in binary. The formula produces n shifted left by this number + 1, then adds n.--Nigel Galloway (talk) 15:24, 3 April 2021 (UTC)
Chunes: Nigel Galloway's explanation is correct. (Thanks, Nigel.) To help me understand it, I've added an alternate FreeBASIC version that works without utilizing log(). The added variable p (which represents 2^int(log(n)/log(2)) 'ratchets' up the left shift amount (the int(log(n)/log(2)) in 2^int(log(n)/log(2))) by double, so the 2*n in k=2*n*2^int(log(n)/log(2)) can just be n, resulting in k = n*p.--Enter your username (talk) 18:33, 4 April 2021 (UTC)
These explanations are correct. To see how it works, suppose I want to duplicate 1001 (9 in decimal). First I multiply by two enough times that I end up with 10010000, then add the 1001 again. So I need to figure out the number of spare digits I need, which is (1+floor(log_2(9)). So I take my original number n, multiply by 2^(1+floor(log_2(n)), and add n. Thebigh (talk) 16:03, 5 April 2021 (UTC)