Code Golf: Numeric equivalent of an Excel column name - excel

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
The challenge
The shortest code by character count that will output the numeric equivalent of an Excel column string.
For example, the A column is 1, B is 2, so on and so forth. Once you hit Z, the next column becomes AA, then AB and so on.
Test cases:
A: 1
B: 2
AD: 30
ABC: 731
WTF: 16074
ROFL: 326676
Code count includes input/output (i.e full program).

Excel, 9 chars :)
Use the right tool for the job:
=COLUMN()

Perl, 36 34 33 31 30 17 15 11 characters
$_=()=A..$_
Usage:
$ echo -n WTF | perl -ple '$_=()=A..$_'
16074
Reduced to 17 by using echo -n to avoid a chop call.
Reduced to 15 by using say instead of print.
Reduced to 11 by using -p instead of say.
Explanation:
A is evaluated in string context and A..$_ builds a list starting at "A" and string-incrementing up to the input string. Perl interprets the ++ operator (and thus ..) on strings in an alphabetic context, so for example $_="AZ";$_++;print outputs BA.
=()= (aka "goatse" operator) forces an expression to be evaluated in list context, and returns the number of elements returned by that expression i.e., $scalar = () = <expr> corresponds to #list = <expr>; $scalar = #list.

J, 17 12 10 characters
26#.64-~av
Example:
26#.64-~av 'WTF'
16074
Explanation:
J parses from right to left.
av returns a list of the ascii indexes of each of the characters in its argument, so for example av'ABC' returns 65 66 67.
Then we subtract 64 from each element of that list with the verb 64-~.
Then we convert the list to base 26 using the #. verb.

Brainf*ck, 81 characters (no whitespace)
,[>>>[->>+++++[-<+++++>]<+<]>[-<+>]<<++++++++[<++++++++>-]<[<->-]<[>>>+<<<-],]>>>
Explanation
,[ // get character input into p[0], enter loop if it isn't null (0)
>>>[->>+++++[-<+++++>]<+<] // take what's in p[3] and multiply by 26, storing it in p[4]
>[-<+>] // copy p[4] back to p[3]
<<++++++++[<++++++++>-]< // store 64 in p[1]
[<->-]< // subtract p[1], which is 64, from the input char to get it's alphabetical index
[>>>+<<<-] // add p[0] to p[3]
,] // get another character and repeat
>>> // move to p[3], where our final result is stored
So you'll notice I didn't actually convert the numerical value to an ascii string for printing. That would likely ruin the fun. But I did the favor of moving the pointer to the cell with the result, so at least it's useful to the machine.
Hey, what do you know, I beat C#!

Ruby 1.8.7, 53 50 46 44 24 17 characters
p ('A'..$_).count
Usage:
$ echo -n ROFL | ruby -n a.rb
326676
$ echo -n WTF | ruby -n a.rb
16074
$ echo -n A | ruby -n a.rb
1

APL
13 characters
Put the value in x:
x←'WTF'
then compute it with:
26⊥(⎕aV⍳x)-65
The only reason J beat me is because of the parentheses. I'm thinking there should be some way to rearrange it to avoid the need for them, but it's been a long day. Ideas?
(Heh, you perl programmers with your 30+ character solutions are so cute!)

Excel (not cheating), 25 chars
Supports up to XFD:
=COLUMN(INDIRECT(A1&"1"))
Installation:
Put the formula in cell A2.
Usage:
Enter the column string in cell A1.
Read the result at cell A2.
54 chars, plus a lot of instructions
Supports ROFL also:
(A2) =MAX(B:B)
(B2) =IFERROR(26*B1+CODE(MID(A$1,ROW()-1,1))-64,0)
Installation:
Clear the whole spreadsheet.
Put the formula (A2) in cell A2.
Put the formula (B2) in cell B2.
Fill formula (B2) to as far down as possible.
Usage:
Enter the column string in cell A1.
Read the result at cell A2.

C# 156 146 118 Chars
using System.Linq;class P{static void Main(string[]a){System.Console.Write(
a[0].Aggregate(0,(t,c)=>(t+c-64)*26)/26);}}
Ungolfed:
using System.Linq;
class P
{
static void Main(string[] a)
{
System.Console.Write(a[0]
.Aggregate(0, (t, c) => (t + c - 64) * 26) / 26);
}
}

Golfscript - 16 chars
[0]\+{31&\26*+}*
$ echo -n WTF | ./golfscript.rb excel.gs
16074
$ echo -n ROFL | ./golfscript.rb excel.gs
326676

Haskell, 50 51 56 chars
main=interact$show.foldl(\x->(26*x-64+).fromEnum)0
Usage:
~:166$ echo -n "ROFL" | ./a.out
326676
~:167$ echo -n "WTF" | ./a.out
16074

Python, 64 49 characters
s=0
for c in raw_input():s=26*s+ord(c)-64
print s
You can also replace raw_input() with input() to reduce the character count by 4, but that then requires the input to contain quotation marks around it.
And here's a subroutine that clocks in at 47 characters:
f=lambda x:len(x)and 26*f(x[:-1])+ord(x[-1])-64

k4 (kdb+), 11 characters
26/:1+.Q.A?
Explanation:
k4 parses left of right
.Q.A is defined within k4 - it is the vector "ABC...XYZ"
? is the find operator - the index of the first match for items in the y arg within the x arg
+1 to offset the index
26/: to convert to base 26
One caveat - this will only work where listed types are passed in:
26/:1+.Q.A? "AD"
30
26/:1+.Q.A? "WTF"
16074
but:
26/:1+.Q.A? ,"A"
1

Powershell, 42 chars
[char[]]$args[($s=0)]|%{$s=$s*26+$_-64};$s

JavaScript 1.8: 66 characters
function a(p)Array.reduce(p,function(t,d)t*26+d.charCodeAt()-64,0)
Javascript 1.8: 72 characters
function a(p)(t=0,p.replace(/./g,function(d)t=t*26+d.charCodeAt()-64),t)
JavaScript 1.6: 83 characters
function a(p){t=0;p.split("").map(function(d){t=t*26+d.charCodeAt(0)-64});return t}
JavaScript: 95 characters
function a(p){r=0;t=1;l=p.length;for(i=0;i<l;i++){r+=(p.charCodeAt(l-1-i)-64)*t;t*=26}return r}
JavaScript: 105 characters
function a(p,i){i=i||0;l=p.length;return p?(p.charCodeAt(l-1)-64)*Math.pow(26,i)+a(p.slice(0,l-1),i+1):0}
Usage:
a("A") // 1
a("B") // 2
a("AD") // 30
a("ABC") // 731
a("WTF") // 16074
a("ROFL") // 326676

Scala, 30 chars
print((0/:args(0))(_*26+_-64))"
Example:
C:\>scala -e "print((0/:args(0))(_*26+_-64))" AD
30

C89, 58 characters
s;main(c){while(c=getchar()+1)s=26*s+c-65;printf("%d",s);}
The input (stdin) must contain only A-Z, no other characters (including newlines) are allowed.

Explanation of Concepts - Excelcification
Nice. I wrote my own version of this with a little more explanation a long time ago at
http://aboutdev.wordpress.com/2009/12/19/excelcification-brain-teaser-code/. Although it's not quite an optimized version!
FYI. The base 26 arithmetic is called hexavigesimal and Excel's maximum column is XFD which converts to 16383 (using 0 as the first cell) which is coincidentally exactly 2^14 cells.
Can anyone guess as to why it is 2^14??

Common Lisp, 103 128 characters
(defun x(s)(reduce(lambda(x y)(+(* 26 x)y))(map 'vector(lambda(b)(-(char-code b)(char-code #\A)-1))s)))

C#, 117 111 chars
No contest compared to the likes of Perl, Ruby and APL but an improvement on the other C#/Java answers given so far.
This uses Horner's rule.
class C{static void Main(string[]a){int t=0;foreach(var c in a[0]){t=(t+c-64)*26;}System.Console.Write(t/26);}}

Perl, 34 characters
map$\=26*$\-64+ord,pop=~/./g;print
Thanks to mobrule for several suggestions.

C#, 148 chars
using System;class P{static void Main(string[]a){var r=0d;int j=0,i=a[0].
Length;while(i-->0)r+=(a[0][i]-64)*Math.Pow(26,j++);Console.WriteLine(r);}}
Ungolfed:
using System;
class P
{
static void Main(string[] a)
{
var r = 0d;
int j = 0, i = a[0].Length;
while (i-- > 0)
r += (a[0][i] - 64) * Math.Pow(26, j++);
Console.WriteLine(r);
}
}

Python - 63 chars
>>> f=lambda z: reduce(lambda x,y: 26*x+y, [ord(c)-64 for c in z])
>>> f('ROFL')
326676

Clojure:
user> (reduce #(+ (* 26 %1) %2) (map #(- (int %) 64) "AD"))
30
user> (reduce #(+ (* 26 %1) %2) (map #(- (int %) 64) "ROFL"))
326676
51 characters, plus the number of characters in the input string.

C:
int r=0;
while(*c)r=r*26+*c++-64;
String is stored in 'c', value is in 'r'.

Ruby 1.9, 21 characters
p'A'.upto(gets).count
Tests:
$ echo -n A| ruby x.rb
1
$ echo -n WTF| ruby x.rb
16074
$ echo -n ROFL| ruby x.rb
326676

Common Lisp, 86 characters.
(defun z(s)(let((a 0))(map nil(lambda(v)(setf a(+(* 26 a)(digit-char-p v 36)-9)))s)a))

Java: 112 124 characters
class C{public static void main(String[]a){int r=0;for(int b:a[0].getBytes())r=26*r+b-64;System.out.print(r);}}

Common Lisp, 81 characters
(defun y(s)(reduce(lambda(x y)(+(* 26 x)(-(char-code y)64)))s :initial-value 0))
Funny that as a new user I can post my own answer but not comment on someone else's. Oh well, apologies if I'm doing this wrong!

MATLAB: 24 characters
polyval(input('')-64,26)
Usage:
>> polyval(input('')-64,26)
(after pressing enter) 'WTF'
ans =
16074
Note: You can get it down to 16 characters if you pre-store the string in x, but I kind of thought it was cheating:
>> x = 'WTF'
x =
WTF
>> polyval(x-64,26)
ans =
16074

PHP - 73 Chars
$n=$argv[1];$s=$i=0;while($i<strlen($n))$s=$s*26+ord($n[$i++])-64;echo$s;
Usage:
php -r '$n=$argv[1];$s=$i=0;while($i<strlen($n))$s=$s*26+ord($n[$i++])-64;echo$s;' AA
> 27

Related

How can i deobfuscate this text?

I've recently found some lua code and what I found inside was some obfuscated string. That made me wonder what sort of obfuscation technique was used there. Does anybody have an idea?
240.06230.0575240.06240.06270.0675250.0625265.06625270.0675250.0625285.07125260.065260.065260.065250.0625265...
https://pastebin.com/raw/7RkxjWQw
If this string is splitted into xxx.yyyy... chunks (exactly three digits before decimal point), then multiply each number by 800/4001 (the results will be integer!), then convert these integer numbers to ASCII, the hidden sequence of 16 floating point numbers would be revealed:
0.0062562944425795
0.036286507766961
0.02127140110477
0.047547837763604
0.041291543321025
0.0025025177770318
0.011261329996643
0.018768883327738
0.017517624439223
0.042542802209541
0.037537766655477
0.016266365550707
0.0087588122196113
0.057557908871731
0.025025177770318
0.026276436658834
Is the puzzle stops here?
Or should we try to decipher it further?
Ok, we could multiply them all by 32767/41 (the results will be integer!)
5
29
17
38
33
2
9
15
14
34
30
13
7
46
20
21
Hmm, the puzzle seems to be really interesting...
Is it the end?
Just googled it.
That's the passwords encrypted, something Roblox-related
So, OP surely doesn't have decoder script :-)
Ok, finally did it.
function decode_password(encoded_password)
local result = ""
local buffer = ""
for x in encoded_password:gsub("%d%d%d%.", "\0%0"):gmatch"%Z+" do
x = math.floor(tonumber(x) / 5.00125 + 0.5)
if x ~= 95 then
buffer = buffer..string.char(x)
elseif buffer ~= "" then
x = math.floor(tonumber(buffer) * 799.195122 + 0.5)
result = result..("qazwsxedcrfjmik,o0 23456-=\\vtgbyhnul.p;;;/[']1789"):sub(x, x)
buffer = ""
end
end
return result
end
Example 1:
local p = '240.06230.0575240.06240.06270.0675250.0625265.06625270.0675250.0625285.07125260.065260.065260.065250.0625265.06625275.06875285.07125265.06625475.11875240.06230.0575240.06255.06375270.0675250.0625280.07270.0675265.06625240.06275.06875275.06875270.0675270.0675285.07125270.0675245.06125475.11875240.06230.0575240.06250.0625245.06125250.0625275.06875245.06125260.065240.06245.06125245.06125240.06260.065275.06875275.06875475.11875240.06230.0575240.06260.065275.06875265.06625260.065275.06875280.07255.06375275.06875275.06875270.0675255.06375270.0675240.06260.065475.11875240.06230.0575240.06260.065245.06125250.0625285.07125245.06125265.06625260.065255.06375255.06375250.0625245.06125240.06250.0625265.06625475.11875240.06230.0575240.06240.06250.0625265.06625240.06250.0625265.06625245.06125275.06875275.06875275.06875275.06875240.06255.06375245.06125280.07475.11875240.06230.0575240.06245.06125245.06125250.0625270.0675245.06125255.06375250.0625285.07125285.07125285.07125270.0675270.0675260.065255.06375475.11875240.06230.0575240.06245.06125280.07275.06875270.0675280.07280.07280.07255.06375255.06375250.0625275.06875275.06875255.06375280.07475.11875240.06230.0575240.06245.06125275.06875265.06625245.06125275.06875270.0675250.0625260.065260.065255.06375285.07125250.0625250.0625255.06375475.11875240.06230.0575240.06260.065250.0625265.06625260.065250.0625280.07240.06250.0625250.0625240.06285.07125265.06625260.065245.06125475.11875240.06230.0575240.06255.06375275.06875265.06625255.06375275.06875275.06875270.0675270.0675270.0675265.06625265.06625260.065275.06875275.06875475.11875240.06230.0575240.06245.06125270.0675250.0625270.0675270.0675255.06375270.0675265.06625265.06625265.06625240.06275.06875240.06275.06875475.11875240.06230.0575240.06240.06280.07275.06875265.06625280.07280.07245.06125250.0625250.0625245.06125285.07125270.0675245.06125245.06125255.06375475.11875240.06230.0575240.06265.06625275.06875265.06625265.06625275.06875285.07125240.06280.07280.07275.06875245.06125275.06875255.06375245.06125475.11875240.06230.0575240.06250.0625265.06625240.06250.0625265.06625245.06125275.06875275.06875275.06875275.06875240.06255.06375245.06125280.07475.11875240.06230.0575240.06250.0625270.0675250.0625275.06875270.0675260.065255.06375270.0675270.0675265.06625280.07280.07255.06375260.065475.11875'
print(decode_password(p)) --> stophackingme123
Example 2:
for _, info in ipairs(loginDatabase) do
print(info.username, decode_password(info.password))
end

convert input to string

How to convert numbers to the first letters of the alphabet? . I want to use this code for me. But I need alphabets for 10,11,12,13 etc. for example if the user will enter 10 , the program will print j for 11 -->"k" . How cam I do this.
My code is same in the link above
You can use this BASH function:
cnvt() { printf "\x$(printf '%x' $((97 + $1 -1)))\n"; }
Test it:
cnvt 10
j
cnvt 11
k
cnvt 26
z
You can use ASCII table for this.
If user inputs 10 you can add 87 and get "a" = 97.
This way input 11 will get a value of "b" = 98.

Can't remove \x strings

I made some researches to delete strings like \x__ . But it is not working.
Here is what i want to do:
i have a string like this:
j_r="some characters \xe2\x84\xc2 some other characters"
In my program, i only want to get:
"some characters some other characters"
Here is what i tried:
c=0
j_r=list(j_r)
while c < len(j_r):
if j_r[c]=='\\':
c+=3
j_f.append(j_r[c])
c+=1
print(j_f)
And here is what it prints:
['s','o','m','e',' ','c','h','a','r','a','c','t','e','r','s']
So i lost the second part of the string that i wanted to keep :'(
May someone help please.
Thank you very much.
(sorry for my english... i am french)
Try checking out this code.
The hex variables that you have created should first be checked since \xe2 is treated as on character.
j_r="some characters \xe2\x84\xc2 some other characters"
c=0
j_r=list(j_r)
j_f = list()
print('Hello World!')
while c < len(j_r):
a = int(j_r[c].encode('hex'), 16)
if(a == 32 or ((a >= 65 and a <= 90)or ( a >= 97 and a<= 122))):
j_f.append(j_r[c])
c += 1
print(j_f)
I hope this code help you with your problem.
What you're getting is bytes, and you want text from it. Therefore you need to decode it.
3>> b'Battlefield: Bad Company\xe2\x84\xa2 2'.decode('utf-8')
'Battlefield: Bad Company™ 2'

Input as many characters as possible in notepad with fewest keyboard typings [duplicate]

This is an interview question from google. I am not able to solve it by myself. Can somebody shed some light?
Write a program to print the sequence of keystrokes such that it generates the maximum number of character 'A's. You are allowed to use only 4 keys: A, Ctrl+A, Ctrl+C and Ctrl+V. Only N keystrokes are allowed. All Ctrl+ characters are considered as one keystroke, so Ctrl+A is one keystroke.
For example, the sequence A, Ctrl+A, Ctrl+C, Ctrl+V generates two A's in 4 keystrokes.
Ctrl+A is Select All
Ctrl+C is Copy
Ctrl+V is Paste
I did some mathematics. For any N, using x numbers of A's , one Ctrl+A, one Ctrl+C and y Ctrl+V, we can generate max ((N-1)/2)2 number of A's. For some N > M, it is better to use as many Ctrl+A's, Ctrl+C and Ctrl+V sequences as it doubles the number of A's.
The sequence Ctrl+A, Ctrl+V, Ctrl+C will not overwrite the existing selection. It will append the copied selection to selected one.
There's a dynamic programming solution. We start off knowing 0 keys can make us 0 A's. Then we iterate through for i up to n, doing two things: pressing A once and pressing select all + copy followed by paste j times (actually j-i-1 below; note the trick here: the contents are still in the clipboard, so we can paste it multiple times without copying each time). We only have to consider up to 4 consecutive pastes, since select, copy, paste x 5 is equivalent to select, copy, paste, select, copy, paste and the latter is better since it leaves us with more in the clipboard. Once we've reached n, we have the desired result.
The complexity might appear to be O(N), but since the numbers grow at an exponential rate it is actually O(N2) due to the complexity of multiplying the large numbers. Below is a Python implementation. It takes about 0.5 seconds to calculate for N=50,000.
def max_chars(n):
dp = [0] * (n+1)
for i in xrange(n):
dp[i+1] = max(dp[i+1], dp[i]+1) # press a
for j in xrange(i+3, min(i+7, n+1)):
dp[j] = max(dp[j], dp[i]*(j-i-1)) # press select all, copy, paste x (j-i-1)
return dp[n]
In the code, j represents the total number of keys pressed after our new sequence of keypresses. We already have i keypresses at this stage, and 2 new keypresses go to select-all and copy. Therefore we're hitting paste j-i-2 times. Since pasting adds to the existing sequence of dp[i] A's, we need to add 1 making it j-i-1. This explains the j-i-1 in the 2nd-last line.
Here are some results (n => number of A's):
7 => 9
8 => 12
9 => 16
10 => 20
100 => 1391569403904
1,000 => 3268160001953743683783272702066311903448533894049486008426303248121757146615064636953144900245
174442911064952028008546304
50,000 => a very large number!
I agree with #SB that you should always state your assumptions: Mine is that you don't need to paste twice to double the number of characters. This gets the answer for 7, so unless my solution is wrong the assumption must be right.
In case someone wonders why I'm not checking sequences of the form Ctrl+A, Ctrl+C, A, Ctrl+V: The end result will always be the same as A, Ctrl+A, Ctrl+C, Ctrl+V which I do consider.
By using marcog's solution I found a pattern that starts at n=16. To illustrate this here are the keystrokes for n=24 up to n=29, I replaced ^A with S (select), ^C with C (copy), and ^V with P (paste) for readability:
24: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P
4 * 4 * 4 * 4 * 4 = 1024
25: A,A,A,A,S,C,P,P,P,S,C,P,P,S,C,P,P,S,C,P,P,S,C,P,P
4 * 4 * 3 * 3 * 3 * 3 = 1296
26: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,S,C,P,P,S,C,P,P
4 * 4 * 4 * 3 * 3 * 3 = 1728
27: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,S,C,P,P
4 * 4 * 4 * 4 * 3 * 3 = 2304
28: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P
4 * 4 * 4 * 4 * 4 * 3 = 3072
29: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P
4 * 4 * 4 * 4 * 4 * 4 = 4096
After an initial 4 As, the ideal pattern is to select, copy, paste, paste, paste and repeat. This will multiply the number of As by 4 every 5 keystrokes. If this 5 keystroke pattern cannot consume the remaining keystrokes on its own some number of 4 keystroke patterns (SCPP) consume the final keystrokes, replacing SCPPP (or removing one of the pastes) as necessary. The 4 keystroke patterns multiply the total by 3 every 4 keystrokes.
Using this pattern here is some Python code that gets the same results as marcog's solution, but is O(1) edit: This is actually O(log n) due to exponentiation, thanks to IVlad for pointing that out.
def max_chars(n):
if n <= 15:
return (0, 1, 2, 3, 4, 5, 6, 9, 12, 16, 20, 27, 36, 48, 64, 81)[n]
e3 = (4 - n) % 5
e4 = n // 5 - e3
return 4 * (4 ** e4) * (3 ** e3)
Calculating e3:
There are always between 0 and 4 SCPP patterns at the end of the keystroke list, for n % 5 == 4 there are 4, n % 5 == 1 there are 3, n % 5 == 2 there are 2, n % 5 == 3 there are 1, and n % 5 == 4 there are 0. This can be simplified to (4 - n) % 5.
Calculating e4:
The total number of patterns increases by 1 whenever n % 5 == 0, as it turns out this number increases to exactly n / 5. Using floor division we can get the total number of patterns, the total number for e4 is the total number of patterns minus e3. For those unfamiliar with Python, // is the future-proof notation for floor division.
Here's how I would approach it:
assume CtrlA = select all
assume CtrlC = copy selection
assume CtrlV = paste copied selection
given some text, it takes 4 keystrokes to duplicate it:
CtrlA to select it all
CtrlC to copy it
CtrlV to paste (this will paste over the selection - STATE YOUR ASSUMPTIONS)
CtrlV to paste again which doubles it.
From there, you can consider doing 4 or 5 A's, then looping through the above. Note that doing ctrl + a, c, v, v will grow your text exponentially as you loop through. If remaining strokes < 4, just keep doing a CtrlV
The key to interviews # places like Google is to state your assumptions, and communicate your thinking. they want to know how you solve problems.
It's solveable in O(1): Like with the Fibonacci numbers, there is a formula to calculate the number of printed As (and the sequence of keystrokes):
1) We can simplify the problem description:
Having only [A],[C-a]+[C-c],[C-v] and an empty copy-paste-buffer
equals
having only [C-a]+[C-c],[C-v] and "A" in the copy-paste-buffer.
2) We can describe the sequence of keystrokes as a string of N chars out of {'*','V','v'}, where 'v' means [C-v] and '*' means [C-a] and 'V' means [C-c]. Example: "vvvv*Vvvvv*Vvvv"
The length of that string still equals N.
The product of the lengths of the Vv-words in that string equals the number of produced As.
3) Given a fixed length N for that string and a fixed number K of words, the outcome will be maximal iff all words have nearly equal lengths. Their pair-wise difference is not more than ±1.
Now, what is the optimal number K, if N is given?
4) Suppose, we want to increase the number of words by appending one single word of length L, then we have to reduce L+1 times any previous word by one 'v'. Example: "…*Vvvv*Vvvv*Vvvv*Vvvv" -> "…*Vvv*Vvv*Vvv*Vvv*Vvv"
Now, what is the optimal word length L?
(5*5*5*5*5) < (4*4*4*4*4)*4 , (4*4*4*4) > (3*3*3*3)*3
=> Optimal is L=4.
5) Suppose, we have a sufficient large N to generate a string with many words of length 4, but a few keystrokes are left; how should we use them?
If there are 5 or more left: Append another word with length 4.
If there are 0 left: Done.
If there are 4 left: We could either
a) append one word with length 3: 4*4*4*4*3=768.
b) or increase 4 words to lenght 5: 5*5*5*5=625. => Appending one word is better.
If there are 3 left: We could either
a) or append one word with length 3 by adjusting the previus word from length 4 to 3: 4*4*4*2=128 < 4*4*3*3=144.
b) increase 3 words to lenght 5: 5*5*5=125. => Appending one word is better.
If there are 2 left: We could either
a) or append one word with length 3 by adjusting the previus two words from length 4 to 3: 4*4*1=16 < 3*3*3=27.
b) increase 2 words to lenght 5: 5*5=25. => Appending one word is better.
If there is 1 left: We could either
a) or append one word with length 3 by adjusting the previus three words from length 4 to 3: 4*4*4*0=0 < 3*3*3*3=81.
b) increase one word to lenght 5: 4*4*5=80. => Appending one word is better.
6) Now, what if we don't have a "sufficient large N" to use the rules in 5)? We have to stick with plan b), if possible!
The strings for small N are:
1:"v", 2:"vv", 3:"vvv", 4:"vvvv"
5:"vvvvv" → 5 (plan b)
6:"vvvvvv" → 6 (plan b)
7:"vvv*Vvv" → 9 (plan a)
8:"vvvv*Vvv" → 12 (plan a)
9:"vvvv*Vvvv" → 16
10:"vvvv*Vvvvv" → 20 (plan b)
11:"vvv*Vvv*Vvv" → 29 (plan a)
12:"vvvv*Vvv*Vvv" → 36 (plan a)
13:"vvvv*Vvvv*Vvv" → 48 (plan a)
14:"vvvv*Vvvv*Vvvv" → 64
15:"vvv*Vvv*Vvv*Vvv" → 81 (plan a)
…
7) Now, what is the optimal number K of words in a string of length N?
If N < 7 then K=1 else if 6 < N < 11 then K=2 ; otherwise: K=ceil((N+1)/5)
Written in C/C++/Java: int K = (N<7)?(1) : (N<11)?(2) : ((N+5)/5);
And if N > 10, then the number of words with length 3 will be: K*5-1-N. With this, we can calculate the number of printed As:
If N > 10, the number of As will be: 4^{N+1-4K}·3^{5K-N-1}
Using CtrlA + CtrlC + CtrlV is an advantage only after 4 'A's.
So I would do something like this (in pseudo-BASIC-code, since you haven't specified any proper language):
// We should not use the clipboard for the first four A's:
FOR I IN 1 TO MIN(N, 4)
PRINT 'CLICK A'
NEXT
LET N1 = N - 4
// Generates the maximum number of pastes allowed:
FOR I IN 1 TO (N1 DIV 3) DO
PRINT 'CTRL-A'
PRINT 'CTRL-C'
PRINT 'CTRL-V'
LET N1 = N1 - 3
NEXT
// If we still have same keystrokes left, let's use them with simple CTRL-Vs
FOR I IN N1 TO N
PRINT 'CTRL-V'
NEXT
Edit
Back to using a single CtrlV in the main loop.
Added some comments to explain what I'm trying to do here.
Fixed an issue with the "first four A's" block.
It takes 3 keystrokes to double your number of As. It only makes sense to start doubling when you have 3 or more As already printed. You want your last allowed keystroke to be a CtrlV to make sure you are doubling the biggest number you can, so in order to align it we will fill in any extra keystrokes after the first three As at the beginning with more As.
for (i = 3 + n%3; i>0 && n>0; n--, i--) {
print("a");
}
for (; n>0; n = n-3) {
print("ctrl-a");
print("ctrl-c");
print("ctrl-v");
}
Edit:
This is terrible, I completely got ahead of myself and didn't consider multiple pastes for each copy.
Edit 2:
I believe pasting 3 times is optimal, when you have enough keystrokes to do it. In 5 keystrokes you multiply your number of As by 4. This is better than multiplying by 3 using 4 keystrokes and better than multiplying by 5 using 6 keystrokes. I compared this by giving each method the same number of keystrokes, enough so they each would finish a cycle at the same time (60), letting the 3-multiplier do 15 cycles, the 4-multiplier do 12 cycles, and the 5-multiplier do 10 cycles. 3^15 = 14,348,907, 4^12=16,777,216, and 5^10=9,765,625. If there are only 4 keystrokes left, doing a 3-multiplier is better than pasting 4 more times, essentially making the previous 4 multiplier become an 8-multiplier. If there are only 3 keystrokes left, a 2-multiplier is best.
Assume you have x characters in the clipboard and x characters in the text area; let's call it "state x".
Let's press "Paste" a few times (i denote it by m-1 for convenience), then "Select-all" and "Copy"; after this sequence, we get to "state m*x".
Here, we wasted a total of m+1 keystrokes.
So the asymptotic growth is (at least) something like f^n, where f = m^(1/(m+1)).
I believe it's the maximum possible asymptotic growth, though i cannot prove it (yet).
Trying various values of m shows that the maximum for f is obtained for m=4.
Let's use the following algorithm:
Press A a few times
Press Select-all
Press Copy
Repeat a few times:
Press Paste
Press Paste
Press Paste
Press Select-all
Press Copy
While any keystrokes left:
Press Paste
(not sure it's the optimal one).
The number of times to press A at the beginning is 3: if you press it 4 times, you miss the opportunity to double the number of A's in 3 more keystrokes.
The number of times to press Paste at the end is no more than 5: if you have 6 or more keystrokes left, you can use Paste, Paste, Paste, Select-all, Copy, Paste instead.
So, we get the following algorithm:
If (less than 6 keystrokes - special case)
While (any keystrokes left)
A
Else
First 5 keystrokes: A, A, A, Select-all, Copy
While (more than 5 keystrokes left)
Paste, Paste, Paste, Select-all, Copy
While (any keystrokes left)
Paste
(not sure it's the optimal one). The number of characters after executing this is something like
3 * pow(4, floor((n - 6) / 5)) * (2 + (n - 1) % 5).
Sample values: 1,2,3,4,5,6,9,12,15,18,24,36,48,60,72,96,144,192,240,288,...
What follows uses the OP's second edit that pasting does not replace existing text.
Notice a few things:
^A and ^C can be considered a single action that takes two keystrokes, since it never makes sense to do them individually. In fact, we can replace all instances of ^A^C with ^K^V, where ^K is a one-key "cut" operation (let's abbreviate it X). We shall see that dealing with ^K is much nicer than the two-cost ^A^C.
Let's assume that an 'A' starts in the clipboard. Then ^V (let's abbreviate it Y) is strictly superior to A and we can drop the latter from all consideration. (In the actual problem, if the clipboard starts empty, in what follows we'll just replace Y with A instead of ^V up until the first X.)
Every reasonable keystroke sequence can thus be interpreted as a group of Ys separated by Xs, for example YYYXYXYYXY. Denote by V(s) the number of 'A's produced by the sequence s. Then V(nXm) = V(n)*V(m), because X essentially replaces every Y in m with V(n) 'A's.
The copy-paste problem is thus isomorphic to the following problem: "using m+1 numbers which sum to N-m, maximimze their product." For example, when N=6, the answer is m=1 and the numbers (2,3). 6 = 2*3 = V(YYXYYY) = V(AA^A^C^V^V) (or V(YYYXYY) = V(AAA^A^C^V). )
We can make a few observations:
For a fixed value of m, the numbers to choose are ceil( (N-m)/(m+1) ) and floor( (N-m)/(m+1) ) (in whatever combination makes the sum work out; more specifically you will need (N-m) % (m+1) ceils and the rest floors). This is because, for a < b, (a+1)*(b-1) >= a*b.
Unfortunately I don't see an easy way to find the value of m. If this were my interview I would propose two solutions at this point:
Option 1. Loop over all possible m. An O(n log n) solution.
C++ code:
long long ipow(int a, int b)
{
long long val=1;
long long mul=a;
while(b>0)
{
if(b%2)
val *= mul;
mul *= mul;
b/=2;
}
return val;
}
long long trym(int N, int m)
{
int floor = (N-m)/(m+1);
int ceil = 1+floor;
int numceils = (N-m)%(m+1);
return ipow(floor, m+1-numceils) * ipow(ceil, numceils);
}
long long maxAs(int N)
{
long long maxval=0;
for(int m=0; m<N; m++)
{
maxval = std::max(maxval, trym(N,m));
}
return maxval;
}
Option 2. Allow m to attain non-integer values and find its optimal value by taking the derivative of [(N-m)/(m+1)]^m with respect to m and solving for its root. There is no analytic solution, but the root can be found using e.g. Newton's method. Then use the floor and ceiling of that root for the value of m, and choose whichever is best.
public int dp(int n)
{
int arr[] = new int[n];
for (int i = 0; i < n; i++)
arr[i] = i + 1;
for (int i = 2; i < n - 3; i++)
{
int numchars = arr[i] * 2;
int j = i + 3;
arr[j] = Math.max(arr[j], numchars);
while (j < n - 1)
{
numchars = numchars + arr[i];
arr[++j] = Math.max(arr[j], numchars);
}
}
return arr[n - 1];
}
Here is my approach and solution with code below.
Approach:
There are three distinct operations that can be performed.
Keystroke A - Outputs one character 'A'
Keystroke (Ctrl-A) + (Ctrl-C) - Outputs nothing essentially. These two keystrokes can be combined into one operation because each of these keystrokes individually make no sense. Also, this keystroke sets up the output for the next paste operation.
Keystroke (Ctrl-V) - Output for this keystroke really depends on the previous (second) operation and hence we would need to account for that in our code.
Now given the three distinct operations and their respective outputs, we have to run through all the permutations of these operations.
Assumption:
Now, some version of this problem states that the sequence of keystrokes, Ctrl+A -> Ctrl+C -> Ctrl+V, overwrite the highlighted selection. To factor in this assumption, only one line of code needs to be added to the solution below where the printed variable in case 2 is set to 0
case 2:
//Ctrl-A and then Ctrl-C
if((count+2) < maxKeys)
{
pOutput = printed;
//comment the below statement to NOT factor
//in the assumption described above
printed = 0;
}
For this solution
The code below will print a couple of sequences and the last sequence is the correct answer for any given N. e.g. for N=11 this will be the correct sequence
With the assumption
A, A, A, A, A, C, S, V, V, V, V, :20:
Without the assumption
A, A, A, C, S, V, V, C, S, V, V, :27:
I have decided to retain the assumption for this solution.
Keystroke Legend:
'A' - A
'C' - Ctrl+A
'S' - Ctrl+C
'V' - Ctrl+V
Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void maxAprinted(int count, int maxKeys, int op, int printed, int pOutput, int *maxPrinted, char *seqArray)
{
if(count > maxKeys)
return;
if(count == maxKeys)
{
if((*maxPrinted) < printed)
{
//new sequence found which is an improvement over last sequence
(*maxPrinted) = printed;
printf("\n");
int i;
for(i=0; i<maxKeys; i++)
printf(" %c,",seqArray[i]);
}
return;
}
switch(op)
{
case 1:
//A keystroke
printed++;
seqArray[count] = 'A';
count++;
break;
case 2:
//Ctrl-A and then Ctrl-C
if((count+2) < maxKeys)
{
pOutput = printed;
//comment the below statement to NOT factor
//in the assumption described above
printed = 0;
}
seqArray[count] = 'C';
count++;
seqArray[count] = 'S';
count++;
break;
case 3:
//Ctrl-V
printed = printed + pOutput;
seqArray[count] = 'V';
count++;
break;
}
maxAprinted(count, maxKeys, 1, printed, pOutput, maxPrinted, seqArray);
maxAprinted(count, maxKeys, 2, printed, pOutput, maxPrinted, seqArray);
maxAprinted(count, maxKeys, 3, printed, pOutput, maxPrinted, seqArray);
}
int main()
{
const int keyStrokes = 11;
//this array stores the sequence of keystrokes
char *sequence;
sequence = (char*)malloc(sizeof(char)*(keyStrokes + 1));
//stores the max count for As printed for a sqeuence
//updated in the recursive call.
int printedAs = 0;
maxAprinted(0, keyStrokes, 1, 0, 0, &printedAs, sequence);
printf(" :%d:", printedAs);
return 0;
}
Using the tricks mentioned in answers above, Mathematically, Solution can be explained in one equation as,
4 + 4^[(N-4)/5] + ((N-4)%5)*4^[(N-4)/5].
where [] is greatest integer factor
There is a trade-off between printing m-A's manually, then using Ctrl+A, Ctrl+C, and N-m-2 Ctrl+V. The best solution is in the middle. If max key strokes = 10, the best solution is typing 5 A's or 4 A's.
try using this Look at this http://www.geeksforgeeks.org/how-to-print-maximum-number-of-a-using-given-four-keys/ and maybe optimize a bit looking for the results around the mid point.
Here is my solution with dynamic programming, without a nested loop, and which also prints the actual characters that you'd need to type:
N = 52
count = [0] * N
res = [[]] * N
clipboard = [0] * N
def maybe_update(i, new_count, new_res, new_clipboard):
if new_count > count[i] or (
new_count == count[i] and new_clipboard > clipboard[i]):
count[i] = new_count
res[i] = new_res
clipboard[i] = new_clipboard
for i in range(1, N):
# First option: type 'A'.
# Using list concatenation for 'res' to avoid O(n^2) string concatenation.
maybe_update(i, count[i - 1] + 1, res[i - 1] + ['A'], clipboard[i - 1])
# Second option: type 'CTRL+V'.
maybe_update(i, count[i - 1] + clipboard[i - 1], res[i - 1] + ['v'],
clipboard[i - 1])
# Third option: type 'CTRL+A, CTRL+C, CTRL+V'.
# Assumption: CTRL+V always appends.
if i >= 3:
maybe_update(i, 2 * count[i - 3], res[i - 3] + ['acv'], count[i - 3])
for i in range(N):
print '%2d %7d %6d %-52s' % (i, count[i], clipboard[i], ''.join(res[i]))
This is the output ('a' means 'CTRL+A', etc.)
0 0 0
1 1 0 A
2 2 0 AA
3 3 0 AAA
4 4 0 AAAA
5 5 0 AAAAA
6 6 3 AAAacv
7 9 3 AAAacvv
8 12 3 AAAacvvv
9 15 3 AAAacvvvv
10 18 9 AAAacvvacv
11 27 9 AAAacvvacvv
12 36 9 AAAacvvacvvv
13 45 9 AAAacvvacvvvv
14 54 27 AAAacvvacvvacv
15 81 27 AAAacvvacvvacvv
16 108 27 AAAacvvacvvacvvv
17 135 27 AAAacvvacvvacvvvv
18 162 81 AAAacvvacvvacvvacv
19 243 81 AAAacvvacvvacvvacvv
20 324 81 AAAacvvacvvacvvacvvv
21 405 81 AAAacvvacvvacvvacvvvv
22 486 243 AAAacvvacvvacvvacvvacv
23 729 243 AAAacvvacvvacvvacvvacvv
24 972 243 AAAacvvacvvacvvacvvacvvv
25 1215 243 AAAacvvacvvacvvacvvacvvvv
26 1458 729 AAAacvvacvvacvvacvvacvvacv
27 2187 729 AAAacvvacvvacvvacvvacvvacvv
28 2916 729 AAAacvvacvvacvvacvvacvvacvvv
29 3645 729 AAAacvvacvvacvvacvvacvvacvvvv
30 4374 2187 AAAacvvacvvacvvacvvacvvacvvacv
31 6561 2187 AAAacvvacvvacvvacvvacvvacvvacvv
32 8748 2187 AAAacvvacvvacvvacvvacvvacvvacvvv
33 10935 2187 AAAacvvacvvacvvacvvacvvacvvacvvvv
34 13122 6561 AAAacvvacvvacvvacvvacvvacvvacvvacv
35 19683 6561 AAAacvvacvvacvvacvvacvvacvvacvvacvv
36 26244 6561 AAAacvvacvvacvvacvvacvvacvvacvvacvvv
37 32805 6561 AAAacvvacvvacvvacvvacvvacvvacvvacvvvv
38 39366 19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacv
39 59049 19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvv
40 78732 19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvv
41 98415 19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvvv
42 118098 59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacv
43 177147 59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv
44 236196 59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvv
45 295245 59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvvv
46 354294 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacv
47 531441 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv
48 708588 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvv
49 885735 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvvv
50 1062882 531441 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacv
51 1594323 531441 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv
If N key Strokes are allowed, then the result is N-3.
A's -> N-3
CTRL+A -> Selecting those N Characters :+1
CTRL+C -> Copying those N Characters :+1
Ctrl+V -> Pasting the N Characters. :+1
i.e., (Since we have selected the whole characters using CTRL+A) Replacing these existing N-3 characters with the copied N-3 Characters(which is overriding the same characters) and the result is N-3.

how to get the number from a string in matlab

I want to how know to get certain numbers from a string in matlab. For example, I have a string:
'ABCD_01 36_00 3 .txt', (there is spacing between 01 and 36)
What I need is to get the number 36 and 3. How can I do it in matlab? I've tried finding the answer from previous posts but can not find one that fits this purpose. Thanks for the help.
Regular expressions:
>> str = 'ABCD_01 36_00 3 .txt';
>> t = str2double( regexp(str,'.* (\d+)_.* (\d+)','tokens','once') )
t =
36 3
If the filenames always start with four characters you can do:
>> filename = 'ABCD_01 36_00 3 .txt';
>> sscanf(filename, '%*4c_%*u %u_%*u %u.txt')
ans =
36
3

Resources