Skip to main content
The National Cipher Challenge

Programming

  • This topic has 47 replies, 12 voices, and was last updated 1 week, 4 days ago by _madness_.
Viewing 15 posts - 31 through 45 (of 50 total)
  • Author
    Posts
  • #98146
    ByteInBits
    Participant

    #######################################################################
    Did you know that there are 362879 consecutive entries containing the
    17 letter phrase starting at the 390304790967593360819076480th entry
    and ending in the 390304790967593360819439359th entry!
    #######################################################################

    \\ HERE ARE MY PARI-gp CODE WORKOUTS
    \\ ————————————————–
    \\ find how many more lines, if any, below the given entry
    s=390304790967593360819076481;
    v=numtoperm(26,s);
    vs=v;
    u=v[1..17];
    c=0;until(v[1..17]!=u,c++;s-=1;v=numtoperm(26,s));
    v=numtoperm(26,s+1);
    print(” : “,c-1,”\n : “,vs,”\n : “,v,”\n : “,s+1);

    : 1
    : [26, 5, 2, 18, 1, 19, 4, 15, 14, 20, 6, 12, 25, 13, 21, 3, 8, 7, 9, 10, 11, 16, 17, 22, 24, 23]
    : [26, 5, 2, 18, 1, 19, 4, 15, 14, 20, 6, 12, 25, 13, 21, 3, 8, 7, 9, 10, 11, 16, 17, 22, 23, 24]
    : 390304790967593360819076480

    \\ ————————————————–
    \\ find how many more lines above the given entry
    s=390304790967593360819076481;
    v=numtoperm(26,s);
    vs=v;
    u=v[1..17];
    c=0;until(v[1..17]!=u,c++;s+=1;v=numtoperm(26,s));
    v=numtoperm(26,s-1);
    print(” : “,c-1,”\n : “,vs,”\n : “,v,”\n : “,s-1);

    : 362878
    : [26, 5, 2, 18, 1, 19, 4, 15, 14, 20, 6, 12, 25, 13, 21, 3, 8, 7, 9, 10, 11, 16, 17, 22, 24, 23]
    : [26, 5, 2, 18, 1, 19, 4, 15, 14, 20, 6, 12, 25, 13, 21, 3, 8, 24, 23, 22, 17, 16, 11, 10, 9, 7]
    : 390304790967593360819439359

    \\ ————————————————
    \\ Find all entry lines that give the message
    \\ (lowest entry computed separately, see above
    \\ found to be one less than 390304790967593360819076481)
    s=390304790967593360819076480;\\ lowest entry
    v=numtoperm(26,s);
    sv=v;
    u=v[1..17];
    \\ find how many more than the given entry
    c=0;while(v[1..17]==u,c++;s+=1;v=numtoperm(26,s));
    {print(“\n Lines with phrase = \t”,c-1);
    print(” Last Entry Line is \t”,s-1);
    print(” Check entry numbers \t”,v);
    print(” against start Line \t”,sv);
    print(“\t\t\tThe first 17 numbers should match”);}

    Lines with phrase = 362879
    Last Entry Line is 390304790967593360819439359
    Check entry numbers [26, 5, 2, 18, 1, 19, 4, 15, 14, 20, 6, 12, 25, 13, 21, 3, 9, 7, 8, 10, 11, 16, 17, 22, 23, 24]
    against start Line [26, 5, 2, 18, 1, 19, 4, 15, 14, 20, 6, 12, 25, 13, 21, 3, 8, 7, 9, 10, 11, 16, 17, 22, 23, 24]
    The first 17 numbers should match

    \\ Confirm The Decryptions

    \\ Lowest line entry
    entry=390304790967593360819076480;
    alphaU=Vec(Str(ABCDEFGHIJKLMNOPQRSTUVWXYZ));
    v=numtoperm(26,entry);
    for(i=1,#v,print1(alphaU[v[i]]));
    [deleted output answer]*

    \\ highest line entry
    entry=390304790967593360819439359;
    alphaU=Vec(Str(ABCDEFGHIJKLMNOPQRSTUVWXYZ));
    v=numtoperm(26,entry);
    for(i=1,#v,print1(alphaU[v[i]]));
    [deleted output answer]*

    *both check out to be the same

    Addendum:
    Of the 26 numbers/letters 17 make the phrase leaving 9 to be arranged in 9! = 362880 ways.
    Actually 9!-1 so 362879 will be the count of entries that have the phrase.
    These entry line numbers start at 390304790967593360819076480 and if we add
    362879 to that they finish at 390304790967593360819439359

    #98057
    Astralica
    Participant

    @BytesInBits

    Whoops, I didn’t see that. After adding a counter to my code, it appears there are 4563 sets.

    Here’s my solution for question 1, as it appears Harry has forgotten about it.
    All in one line, because why not? (I swear my code normally isn’t as garbage as Q1 and Q3…)

    print(next(filter(lambda x: all(x % (4, 5, 7, 11, 17)[i] == (3, 1, 2, 2, 12)[i] for i in range(5)), range(5000, 50000))))
    Output: 29031

    #98171
    _madness_
    Participant

    @ByteInBits, your MD5 sum is for the NEXT permutation. By my example, you should start with 1 and not 0.

    @upsidedown, your MD5 sum is correct.

    #98180
    ByteInBits
    Participant

    /*
    MY CODE TO MY FIRST 3 QUESTIONS
    ================================
    For what it is worth, good or bad, here is the code I wrote using PARI-gp.
    I have not included the code’s print out for Q#3 as every one who posted code and answer
    gave the correct answer, well done y’all!

    I very rarely use python (a wonderful and most popular language these days) and the
    code given in the forum by participants has been very helpful, I hope it has for others too.

    Some of you are really knowledgeable and clever!
    */
    \\ ======================================================== Question #1
    \\ FIND X

    \\ ===================================================== PARI-gp CODE
    {for(x=5000,50000,
    a=x%4;b=x%5;c=x%7;d=x%11;e=x%17;
    if(a==3&&b==1&&c==2&&d==2&&e==12,print(“\n\\\\ Answer: “n)));}

    \\ Answer: 29031

    \\ ======================================================== Question #2
    \\ FIND N AND PRIMES

    \\ =================================================== PARI-gp CODE

    \\ CODE TO FIND THE NUMBER
    \\ Try all 4 digit numbers
    for(i=1000,9999,d=divisors(i);if(#d==60,print(“\\\\ “i)));
    \\ 5040
    \\ 7920
    \\ 8400
    \\ 9360

    \\ It is the first 4 digit number 5040 having 60 divisors that we seek
    \\ (There are 3 more 4 digit numbers with 60 divisors but with wrong prime totals)

    \\ CODE TO FIND THE 42 CONSECUTIVE PRIMES THAT ADD TO THE NUMBER 5040
    {true=1;seed=2;
    while(true,
    total=0;
    forprime(p=seed,1000,total+=p;
    p1=nextprime(seed);
    if(total==5040,print1(“\n\\\\ Answer: The consecutive primes “p1” to “p” sum to “total);true=0;break);
    );
    seed=p1+1;
    );}

    \\ Answer: The consecutive primes 23 to 229 sum to 5040

    \\ CODE TO PRINT THE 42 PRIMES:
    total=0;print1(“\\\\ “);forprime(p=23,230,total+=p;print1(p” “);if(total>=5040,break));
    \\ 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229

    \\ OR IF THE START AND END PRIME IS KNOWN:
    count=0;print1(“\\\\ “);forprime(p=23,229,count++;print1(p” “);if(count==42,break));
    \\ 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229

    \\ ======================================================== Question #3
    \\ WAYS WITH MONEY

    \\ ===================================================== PARI-gp Code
    \\ By the way gp ignores all white space/tabs in the code
    \\ the following code is for friendly visual layout only
    \\ ***USER FUNCTION*** prints only the 1st 10 and last 10 sets.
    CountTheCoins()={
    print(“\n\\\\ ===================== PROGRAM OUTPUT ======================”);
    print(“\n\\\\ Please wait for the last 10 to print out\n”);
    print(“\\\\\tset#)\tcoin count of(coin value)”);
    my(purse,count=0);
    for(penny=0,100, \\ 100/1
    for(tuppence= 0,50, \\ 100/2
    for(fivepence= 0,20, \\ 100/5
    for(tenpence= 0,10, \\ 100/10
    for(twentypence= 0,5, \\ 100/20
    for(fiftypence= 0,2,\\ 100/50
    for(pound= 0,1, \\ 100/100
    purse = (penny + tuppence*2 + fivepence*5 + tenpence*10 + twentypence*20 + fiftypence*50 + pound*100);
    if(purse==100,
    if(count<10||count>=4553,\\ pre computed (4563-10)
    print(“\\\\\t”,count+1,”)\t”,penny,”(1p) “,tuppence,”(2p) “,fivepence,”(5p) “,tenpence,”(10p) “,
    twentypence,”(20p) “,fiftypence,”(50p) “,pound,”(100p) “);
    );count++;
    )
    )
    )
    )
    )
    )
    )
    );
    print(“\n\\\\ The number of possible ways (sets) is: “, count);}
    \\ ***Call the function***
    CountTheCoins();
    \\
    /*
    ===============================================================================
    You can safely copy ALL of this post and paste it but you will see some duplicated answers
    If you want you can copy and paste the gp code into an online compiler and
    execute it to get/see output.
    ===============================================================================
    */

    #98187
    ByteInBits
    Participant

    =========================================== PROGRAMMING QUEST #4

    PRODUCE THE LARGEST INTERGER FROM A SET OF INTEGERS BY ORDERING AND CONCATENATION

    Here is a set and the largest number obtained to check your code against
    [2, 34, 7, 98, 9, 77, 41, 5] The 8 integers arrange to : 998777541342

    VARIOUS TASKS
    Code functions to :
    (A) Return a random positive integer having a random count of digits between 1 and 6,
    (B) Return a random set of between 5 and 10 integers using the (A) generated integers.
    (C) Concatenate the integers in the set (B) in such an order that the largest integer is returned.
    (D) Show (print) the integers in the set (B) followed by the largest number (C) produced.
    Produce 10 Different Results of (D)

    \\ EXAMPLE OUTPUT (will be different for each run)
    \\ Set1 [3, 11, 48427, 22944, 6677, 1849, 9, 4] The 8 integers arrange to : 96677484274322944184911
    \\ Set2 [58615, 3, 934, 3, 23666] The 5 integers arrange to : 934586153323666
    \\ Set3 [88978, 69576, 83499, 31, 27398, 856, 219, 23991] The 8 integers arrange to : 889788568349969576312739823991219
    \\ Set4 [3, 7119, 49, 533, 3614, 512, 45, 4711, 4761] The 9 integers arrange to : 711953351249476147114536143
    \\ Set5 [3852, 3, 41977, 98, 3488, 22, 1117] The 7 integers arrange to : 9841977385234883221117
    \\ Set6 [8335, 17293, 29, 16, 79, 7, 59785, 1, 96358] The 9 integers arrange to : 963588335797597852917293161
    \\ Set7 [94, 68252, 8984, 11793, 95] The 5 integers arrange to : 959489846825211793
    \\ Set8 [5767, 7, 17279, 3366, 38, 29995, 3, 588, 52179] The 9 integers arrange to : 758857675217938336632999517279
    \\ Set9 [68, 6, 4761, 42, 8855, 13, 8432, 3661, 332] The 9 integers arrange to : 88558432686476142366133213
    \\ Set10 [4374, 98, 83483, 1, 4249, 3] The 6 integers arrange to : 98834834374424931

    Extra non-random sets:
    What is the largest integer that can be formed :
    1] from a set of the first 50 positive integers in ascending order 1 .. 50
    2] from a set of all positive even integers below and including 100 in ascending order
    3] from a set of all positive odd integers below and including 99 in ascending order
    4] from the first 20 prime numbers in ascending order

    Give MD5’s for the 4 non-random large integers.
    1] MD5: ?
    2] MD5: ?
    3] MD5: ?
    4] MD5: ?

    #98369
    ByteInBits
    Participant

    =========================================== PROGRAMMING QUEST #4 UPDATE

    THOSE LAST 5 (EXTRA NON-RANDOM SETS) ARE FAR TOO SIMPLE (JUST WRITE THEM OUT IN REVERSE)
    PLEASE REPLACE THEM WITH THE FOLLOWING

    Have your code return the largest integer for each of these 5 sets:

    \\ Set1 [699, 1, 58, 31, 1698, 19998, 6, 3] The 8 integers arrange to : ?
    \\ Set2 [5, 6, 39516, 412, 95, 841, 5953, 98586, 7] The 9 integers arrange to : ?
    \\ Set3 [768, 2395, 43, 25, 83, 699, 331] The 7 integers arrange to : ?
    \\ Set4 [8189, 44368, 786, 9267, 6531, 65, 5117, 63, 26828] The 9 integers arrange to : ?
    \\ Set5 [25459, 9469, 36, 3524, 87] The 5 integers arrange to : ?

    Give MD5’s for the 5 non-random large integers.
    1] MD5: ?
    2] MD5: ?
    3] MD5: ?
    4] MD5: ?

    #98371
    ByteInBits
    Participant

    @_madness_

    Normally I would smile and let it pass but I have to take issue with you
    to come to some understanding.

    In post #98171 you state:
    @ByteInBits, your MD5 sum is for the NEXT permutation. By my example, you should start with 1 and not 0.

    This make you incorrect with the entry number!!
    (standard practice doese not start at 1, and you never stated the deviation)

    With PARI function numtoperm()
    The numbering used is the standard lexicographic ordering, starting at 0.
    Thus
    numtoperm(26,0)
    = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]

    The entry number you gave was 390304790967593360819076481
    and the PARI function

    numtoperm(26,390304790967593360819076481) gives
    [26, 5, 2, 18, 1, 19, 4, 15, 14, 20, 6, 12, 25, 13, 21, 3, 8, 7, 9, 10, 11, 16, 17, 22, 24, 23]

    And those numbers referencing the alphabet positions produce the the following
    ZEBRASDONTFLYMUCHGIJKPQVXW

    and MD5 of ZEBRASDONTFLYMUCHGIJKPQVXW is
    F09C437C737F2B836B1EC48A5056148E which is what I gave.

    The PARI inverse function permtonum
    permtonum([26, 5, 2, 18, 1, 19, 4, 15, 14, 20, 6, 12, 25, 13, 21, 3, 8, 7, 9, 10, 11, 16, 17, 22, 24, 23])
    = 390304790967593360819076481
    confirms the entry number

    So are you saying that the PARI-gp’s inbuilt functions are at fault?!

    Anyone else care to comment in this matter?

    #98359
    852952ae12022b7d6115da0fd2c3fac7a8296a5865b69165b6955e727fa58571
    Participant

    Hi folks,
    I am fairly new to Python programming and am primarily learning it through my GCSE Computer Science course. As part of this, one of my assignments is to complete a two-player dice game according to ‘Task 2’ of this specification.

    Here are the key details if you don’t want to open the link:

    Katarina is developing a two-player dice game.
    The players roll two 6-sided dice each and get points depending on what they
    roll. There are 5 rounds in a game. In each round, each player rolls the two dice.
    The rules are:
    • The points rolled on each player’s dice are added to their score.
    • If the total is an even number, an additional 10 points are added to their score.
    • If the total is an odd number, 5 points are subtracted from their score.
    • If they roll a double, they get to roll one extra die and get the number of points rolled added to
    their score.
    • The score of a player cannot go below 0 at any point.
    • The person with the highest score at the end of the 5 rounds wins.
    • If both players have the same score at the end of the 5 rounds, they each roll 1 die and
    whoever gets the highest score wins (this repeats until someone wins).
    Only authorised players are allowed to play the game.
    Where appropriate, input from the user should be validated.

    Sorry I had to edit the rest, we don’t usually include offsite links as we can’t control the content. Hope you understand, Jodie

    #98394
    robb
    Participant

    @_madness_ @ByteInBits
    I use PARI for various purposes and agree that numtoperm(26,390304790967593360819076481) indeed gives [26, 5, 2, 18, 1, 19, 4, 15, 14, 20, 6, 12, 25, 13, 21, 3, 8, 7, 9, 10, 11, 16, 17, 22, 24, 23].

    From the challenge perspective coding increasing loops in python or other languages would generate the last few digits as 17, 22, 23, 24 i.e. the alphabetical arrangement QVWX as required.

    When I under took the challenge, I started with a normal ORDERED alphabet, and used PARI to manually find the highest powers of 26, 25, 24 etc below the required number to generate the sequence 26, 5, 2, 18, 1, 19, 4, 15, 14, 20, 6, 12, 25, 13, 21, 3, 8 then removed the corresponding letter from my ordered alphabet. This gave me ZEBRASDONTFLYMUCH and left the ordered letters GIJKPQVWX. To me this was logical and in keeping ciphers like the key substitution order used in the main challenges.

    I hope this helps add perspective.

    #98400
    _madness_
    Participant

    @8529…
    I have a better idea for you. Design the game so that no server is needed; i.e., two players play the game by peer-to-peer interactions. You will need to design a way that dice can be randomized so that both players are convinced that it was done randomly and neither player can cheat.

    Ah, now the dice rolling is a really interesting cryptographic problem. You might want to start by considering how you could flip a coin with someone on the other side of the world who really doesn’t trust you. They even think you can cheat if you video the process! There is a beautiful coin tossing algorithm that gets round this by using the fact that if p and q are two different primes then there are four square roots of 1 mod pq. I leave you to look this up. Harry

    #98418
    ByteInBits
    Participant

    Thanks for your input @rob
    I see what you mean. 😉

    It would have been better if @_madness_ had asked for the message only, still it must be quiet a challenge
    as apart from @upsidedown and yourself, as of this posting, no one else has submitted a response.

    Will you be putting your code up @_madness_?

    #98417
    Astralica
    Participant

    @ByteInBits

    Is this correct? (For the replacement ones.)
    Honestly, it’d probably be easier to do it manually, but here’s the result my code gives.
    c8a03543e09418b43116ea62ed2dd0b6
    9801ec0d80cdae27abc84c53844cb7b0
    e7a6e8c0943b4c986ddd92ad762be009
    db9f2879c024590ca4f97812f7aa2dcd
    744fa68f2e80a0c13ef4b821ca60e3a7

    #98434
    ByteInBits
    Participant

    @Astralica
    All your MD5’s are correct
    AGREED, IT IS EASIER TO DO IT MANUALLY but not always easy, for some, to program code do it 😉 that is the quest.
    Care to put up your code, it should do the A,B,C & D which I forgot ask for.

    #98437
    Astralica
    Participant

    Here is my code (Python):

    First, I normalise all of the numbers to be the same length (so I can compare them). If the number is too short, I simply repeat the last digit.
    Then, I sort the original list with respect to the normalised list and concatenate, giving the final solution.

    There is a slight error if there are two normalised numbers that are the same.
    E.g. 100 and 10 are both normalised to 100 (last digit is repeated).
    It will prefer putting 100 first, when it should be 10. It’s a small fix and I just need to check for this, but I’m kinda busy.

    def reorder(arr):
       maxDigits = max(map(lambda x: len(str(x)), arr))
       normalised = map(lambda x: int(str(x) + str(x)[-1]*(maxDigits-len(str(x)))), arr)
       pairs = sorted(zip(normalised, arr), reverse=True)
       return "".join(str(v) for v in map(lambda v: v[1], pairs))
    #98459
    _madness_
    Participant

    @ByteInBits,
    I wrote a function to do the main part:

    def nth_permutation(n,objects):
        perm = []
        n -= 1
        while len(objects) > 0:
            m = int(n/factorial(len(objects)-1))
            n -= m * factorial(len(objects)-1)
            perm.append(objects[m])
            objects.pop(m)
        return perm
    
Viewing 15 posts - 31 through 45 (of 50 total)
  • You must be logged in to reply to this topic.
Report a problem