Maximum number of characters using keystrokes A, Ctrl+A, Ctrl+C and Ctrl+V

前端 未结 14 1473
忘掉有多难
忘掉有多难 2020-12-07 07:03

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 suc

相关标签:
14条回答
  • 2020-12-07 07:25

    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.

    0 讨论(0)
  • 2020-12-07 07:26

    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

    0 讨论(0)
  • 2020-12-07 07:34

    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.

    0 讨论(0)
  • 2020-12-07 07:35

    Here is my approach and solution with code below.

    Approach:

    There are three distinct operations that can be performed.

    1. Keystroke A - Outputs one character 'A'
    2. 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.
    3. 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;
    }    
    
    0 讨论(0)
  • 2020-12-07 07:36

    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,...

    0 讨论(0)
  • 2020-12-07 07:36
    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];
    }
    
    0 讨论(0)
提交回复
热议问题