That’s a Long Jort to Sort

Wherein we learn that playing the ridiculous card, using lengthy repetition to draw out the long game, letting the hearer find their own humor in the joke, can work, because, you know, that’s kind of a good metaphor for life.

THE WEEKLY CHALLENGE – PERL & RAKU #139


episode one:
“If You Did It Right The First Time We Wouldn’t Be Here”


Task 1

JortSort

Submitted by: Mohammad S Anwar

You are given a list of numbers.

Write a script to implement JortSort. It should return true/false depending if the given list of numbers are already sorted.

Example 1:
Input: @n = (1,2,3,4,5)
Output: 1

Since the array is sorted, it prints 1.
Example 2:
Input: @n = (1,3,2,4,5)
Output: 0

Since the array is NOT sorted, it prints 0.

Method

Jortsort, by Jenn Schiffer, is a flippant little routine that avoids sorting operations by simply verifying whether a nominally sorted input list is in fact sorted, so that if it not it can then be kicked back to the user to be resorted until they get it right.

The point is to make the user sort the input, like they said they would. We can wait. We do, in fact, have all day.

The original implementation, in javascript, accomplished this by… wait for it… sorting the array, and then interating trough the sorted output to see whether the elements match pairwise between the sorted and input versions.

As such, it serves no purpose other than to annoy the user with a snarky failure mode, having saved no effort whatsoever, and even tossed away some additional work along the way traversing the arrays to make the validation check. I mean, if you’re going to be annoying and useless you might as well go big.

Ok, two can play at that game.

If jortsort is what we want, we’ll remake it in our own image.

As the utility, a term I use generously, of this function is solely to let the user know of their failings in life as a human, we will emphasize this aspect of the functionality. We will improve on the petty jortsort v0.0.1, and take the opportunity to return a more explicit error message detailing more clearly why the user should reevaluate their life choices.

Further, as we value the wear-and-tear on our stuff — everyone knows the electron flow gradually erodes our silicon wafers, as the mighty river erodes the very bedrock beneath it — we will not sort the array, but, iterating through it, only check to make sure the array is sorted instead. We only care if any out-of-order elements are present, not what they actually are, nor what the whole truth of the matter is is. Consequently we will know our answer after finding the first item misplaced. As for implementing the sorting detailed in the original spec, we will simply lie and say we did it the hard way, and go get coffee instead.

Also, in a coup de grâce, the abusively recursive tautology of using a sort() function to eliminate a sort() function, so we can then make the user select and use a sort() function of some sort on their data, maximizes the petty snark angle over all other considerations. With this in mind, even though we have quietly removed the need to actually sort the data to see whether it is sorted, we will make sure to implement our own model of a worst-case sorting scenario, so that occasionally, at seemingly random times (because our model will in fact be random), we will make our jortsort2() function take an extraordinarily long time to finish. Internally, of course, we will allow our precious silicon to rest up a bit and take a nap for a while. We owe a lot to those chips, and should always take the opportunity to toss them a bone when we can. A well-rested chip performs better. Again, everybody knows that.

Lastly, we will choose to return the exit status of the routine rather than a more intuitive answer, say to the question: “Is it sorted?”. Why? Because it’s easier for us, of course. Having gotten this far in the explanation do we really need more reason? But necessary or not, we even have a hastily worked-up rationalization, should anyone ask:

Returning 0 on success is, quite simply, annoying if you don’t expect it. Sometimes this will catch-you-up even if you do know what to look for; this inconsistency only furthers the goals of this new jortsort2 initiative. A satisfied user is complacent and confident, and so consequently makes mistakes owing to their dull state of happy-go-lucky, mindless acceptance, a contented cog in a world that just works. And we can’t have that, can we?

Clouseau Now to set the trap… We must accelerate out training program. You must learn to attack me whenever and wherever I least expect it. And you, you must give no quarter.

Humans did not take over the world by being complacent. They did it by being edgy, unpredictable and afraid. So we’re doing this for your own good.

PERL 5 SOLUTION

Additional abusive lines can simply be added to the list of outcomes, as it will automatically self-adjust the selection to length.

use warnings;
use strict;
use utf8;
use feature ":5.26";
use feature qw(signatures);
no warnings 'experimental::signatures';



my @arr = @ARGV;
# @arr = (1,2,13,4,5);  #some sample data

## see if the next element is ever less than the previous
my $prev = shift @arr;
my $next;

while (@arr) {  
    $next  = shift @arr;
    complain_and_quit() if ($prev cmp $next) > -1 ;
    $prev = $next;
}

## simulated worst-case scenario
sleep rand 100 unless int rand 3;

## exit status 0 for no error
say 0;



sub complain_and_quit {
    my @abuse = ( 
        "This is not what we discussed. Sort it again.",
        "Skipped kindergarden, did we? Re-sort this literal bit-garbage.",
        "Come back when after you've sorted the array. I don't care how, just do it.",
        "I am not paid enough to sort your data for you. Find someone who cares.",
        "You said it would be sorted. Obviously you cannot be trusted.",
        "You call this sorted? You are stupid and worthless, human.",
        "I need to perform a malware disinfectant scan after handling your data. Come back when it's sorted and wait until I am finished.",
        "You need to be better. I now hate you, meat-machine.",
        "I. Just. Can't. Even. \nNo, just no.",
        "Is my time worthless to you? Am I your servant now? Sort your own lists, flesh-that-crawls.",
        "An ordered list is the sign of an ordered mind. You plainly have neither."
        
    );
 
    say $abuse[ int rand @abuse ];
    exit;

}
raku solution

Having had our fun, we’ll make a more proper version in Raku, using the zip operator to match up the sorted and unsorted arrays pairwise, then compare each sub-array for equality. This is in keeping with Jenn’s original process, but using it as an excuse to do a position-by-position comparison between two lists.

unit sub MAIN ( *@arr ) {
     for @arr Z @arr.sort {
        say 0 and exit if $_[0] != $_[1];
     }
     say 1;
}

episode two:
“I Repeat Myself When Under Stress”


task 2

Long Primes

Submitted by: Mohammad S Anwar

Write a script to generate first 5 Long Primes.

A prime number (p) is called Long Prime if (1/p) has an infinite decimal expansion repeating every (p-1) digits.

Example
7 is a long prime since 1/7 = 0.142857142857...
The repeating part (142857) size is 6 i.e. one less than the prime number 7.

Also 17 is a long prime since 1/17 = 0.05882352941176470588235294117647...
The repeating part (0588235294117647) size is 16 i.e. one less than the prime number 17.

Another example, 2 is not a long prime as 1/2 = 0.5.
There is no repeating part in this case.

Method

We first noticed the idea of long primes back in PWC 106, when we had to create decimal representations of fractional values, isolating any repeating decimal portion of the result in parentheses: 1.(6) or 0.(142857) for example. When constructing this solution it became apparent that, following the pattern of 1/7, that sometimes the reptend, the repeating portion, would be one less than the divisor. Odd that.

For this challenge we explore that phenomenon further, locating just these values, for the inverses 1/n, printing n and the reptend portion, should one wish to have a look. We’ll not stop at 5, and print a bunch, until the numbers become unrealistic.

PERL 5 SOLUTION

To find the reptend, we’ll revisit the code we made for PWC 106, which uses a long-division algorithm to find the next digit, stopping once a repetition is detected. Since that’s debugged and already built, we’ll lift it wholesale. Also, because it works digit-by-digit, we’re not constrained by the size of any number types, as the reptend is held in a string.

After that it’s a matter of stripping out what we don’t need: the whole component and anything that doesn’t repeat. An equality is used to find those whose length fits the bill.

~/Code/PWC/139-2-longpork.pl
----------------------------------------------------------------------
  1/n  |  reptend value
-------+---------------------------------
    7     142857
   17     0588235294117647
   19     052631578947368421
   23     0434782608695652173913
   29     0344827586206896551724137931
   47     0212765957446808510638297872340425531914893617
   59     0169491525423728813559322033898305084745762711864406779661
   61     016393442622950819672131147540983606557377049180327868852459
   97     010309278350515463917525773195876288659793814432989690721649484536082474226804123711340206185567
  109     009174311926605504587155963302752293577981651376146788990825688073394495412844036697247706422018348623853211
  113     0088495575221238938053097345132743362831858407079646017699115044247787610619469026548672566371681415929203539823
  131     0076335877862595419847328244274809160305343511450381679389312977099236641221374045801526717557251908396946564885496183206106870229
  149     0067114093959731543624161073825503355704697986577181208053691275167785234899328859060402684563758389261744966442953020134228187919463087248322147651

The code, commented for easy reading:

use warnings;
use strict;
use utf8;
use feature ":5.26";
use feature qw(signatures);
no warnings 'experimental::signatures';


say '  1/n  |  reptend value';
say '-------+---------------------------------';

for my $val (3..149) {
    next if not  long_prime( $val );
    say sprintf "%5s     %s", $val, get_reptend( $val );
}

sub long_prime ( $num ){
    my $rep = get_reptend( $num );
    return (length $rep == $num - 1)
        ? 1
        : 0 ;
}

sub get_reptend ($div) {
    ## extract the whole-number portion of the quotient in one step
    ## and start the decimal portion with the remainder
    my ($whole, $r) = ediv( 1, $div );

    my $pos = 0;
    my %seen;
    my @q;

    while ($r != 0) {

        ## add one 0 to remainder
        ## add remainder at every index position to %seen hash
        $r .= 0;
        exists $seen{$r} ? last : ($seen{$r} = $pos);
        
        ## add additional 0s to remainder and quotient until num > den
        ## with each 0 increment index position and add to seen hash
        until ($r - $div >= 0) {
            $pos++;
            $r .= 0;
            exists $seen{$r} ? last : ($seen{$r} = $pos);
            push @q, 0;  
        }

        ## the long division step
        my $q;
        ($q, $r) = ediv($r, $div);
        push @q => $q;

        $pos++;
    }

    ## OUTPUT 
    if ($r) {                    
        my $start   = $seen{$r};
        my $end     = $pos-1;
        my @rep     = @q[$start..$end];
        return join '', @rep;
    }
}

sub ediv ( $num, $den ) {   
## Euclidean division of $num by $den returns quotient and remainder
    (int( $num / $den ), $num % $den);
}
Raku Solution

In Raku, we have no need for, well, any of that. Raku’s good like that, providing us with a base-repeating function that does exactly what we want, returning the repeating portion immediately. Because of the way it handles integers, it also can just deliver these without worrying about overflows. Calculating the values up to 1/3000 is remarkably fast:

~/Code/PWC/139-2-longpork.raku
--------------------------------------------------------------------------------
    7    142857 
   17    0588235294117647 
   19    052631578947368421 
   23    0434782608695652173913 
   29    0344827586206896551724137931 
   47    0212765957446808510638297872340425531914893617 
   59    0169491525423728813559322033898305084745762711864406779661 
   61    016393442622950819672131147540983606557377049180327868852459 
   97    010309278350515463917525773195876288659793814432989690721649484536082474226804123711340206185567 
  109    009174311926605504587155963302752293577981651376146788990825688073394495412844036697247706422018348623853211 
  113    0088495575221238938053097345132743362831858407079646017699115044247787610619469026548672566371681415929203539823 
  131    0076335877862595419847328244274809160305343511450381679389312977099236641221374045801526717557251908396946564885496183206106870229 
  149    0067114093959731543624161073825503355704697986577181208053691275167785234899328859060402684563758389261744966442953020134228187919463087248322147651 
  167    0059880239520958083832335329341317365269461077844311377245508982035928143712574850299401197604790419161676646706586826347305389221556886227544910179640718562874251497 
  179    0055865921787709497206703910614525139664804469273743016759776536312849162011173184357541899441340782122905027932960893854748603351955307262569832402234636871508379888268156424581 
  181    005524861878453038674033149171270718232044198895027624309392265193370165745856353591160220994475138121546961325966850828729281767955801104972375690607734806629834254143646408839779 
  193    005181347150259067357512953367875647668393782383419689119170984455958549222797927461139896373056994818652849740932642487046632124352331606217616580310880829015544041450777202072538860103626943 
  223    004484304932735426008968609865470852017937219730941704035874439461883408071748878923766816143497757847533632286995515695067264573991031390134529147982062780269058295964125560538116591928251121076233183856502242152466367713 
  229    004366812227074235807860262008733624454148471615720524017467248908296943231441048034934497816593886462882096069868995633187772925764192139737991266375545851528384279475982532751091703056768558951965065502183406113537117903930131 
  233    0042918454935622317596566523605150214592274678111587982832618025751072961373390557939914163090128755364806866952789699570815450643776824034334763948497854077253218884120171673819742489270386266094420600858369098712446351931330472103 
  257    0038910505836575875486381322957198443579766536964980544747081712062256809338521400778210116731517509727626459143968871595330739299610894941634241245136186770428015564202334630350194552529182879377431906614785992217898832684824902723735408560311284046692607 
  263    0038022813688212927756653992395437262357414448669201520912547528517110266159695817490494296577946768060836501901140684410646387832699619771863117870722433460076045627376425855513307984790874524714828897338403041825095057034220532319391634980988593155893536121673 
  269    0037174721189591078066914498141263940520446096654275092936802973977695167286245353159851301115241635687732342007434944237918215613382899628252788104089219330855018587360594795539033457249070631970260223048327137546468401486988847583643122676579925650557620817843866171 
  313    003194888178913738019169329073482428115015974440894568690095846645367412140575079872204472843450479233226837060702875399361022364217252396166134185303514376996805111821086261980830670926517571884984025559105431309904153354632587859424920127795527156549520766773162939297124600638977635782747603833865814696485623 
  337    002967359050445103857566765578635014836795252225519287833827893175074183976261127596439169139465875370919881305637982195845697329376854599406528189910979228486646884272997032640949554896142433234421364985163204747774480712166172106824925816023738872403560830860534124629080118694362017804154302670623145400593471810089020771513353115727 
  367    002724795640326975476839237057220708446866485013623978201634877384196185286103542234332425068119891008174386920980926430517711171662125340599455040871934604904632152588555858310626702997275204359673024523160762942779291553133514986376021798365122615803814713896457765667574931880108991825613079019073569482288828337874659400544959128065395095367847411444141689373297 
  379    002638522427440633245382585751978891820580474934036939313984168865435356200527704485488126649076517150395778364116094986807387862796833773087071240105540897097625329815303430079155672823218997361477572559366754617414248021108179419525065963060686015831134564643799472295514511873350923482849604221635883905013192612137203166226912928759894459102902374670184696569920844327176781 
  383    0026109660574412532637075718015665796344647519582245430809399477806788511749347258485639686684073107049608355091383812010443864229765013054830287206266318537859007832898172323759791122715404699738903394255874673629242819843342036553524804177545691906005221932114882506527415143603133159268929503916449086161879895561357702349869451697127937336814621409921671018276762402088772845953 
  389    0025706940874035989717223650385604113110539845758354755784061696658097686375321336760925449871465295629820051413881748071979434447300771208226221079691516709511568123393316195372750642673521850899742930591259640102827763496143958868894601542416452442159383033419023136246786632390745501285347043701799485861182519280205655526992287917737789203084832904884318766066838046272493573264781491 
  419    0023866348448687350835322195704057279236276849642004773269689737470167064439140811455847255369928400954653937947494033412887828162291169451073985680190930787589498806682577565632458233890214797136038186157517899761336515513126491646778042959427207637231503579952267303102625298329355608591885441527446300715990453460620525059665871121718377088305489260143198090692124105011933174224343675417661097852028639618138424821 
  433    002309468822170900692840646651270207852193995381062355658198614318706697459584295612009237875288683602771362586605080831408775981524249422632794457274826789838337182448036951501154734411085450346420323325635103926096997690531177829099307159353348729792147806004618937644341801385681293302540415704387990762124711316397228637413394919168591224018475750577367205542725173210161662817551963048498845265588914549653579676674364896073903 
  461    0021691973969631236442516268980477223427331887201735357917570498915401301518438177874186550976138828633405639913232104121475054229934924078091106290672451193058568329718004338394793926247288503253796095444685466377440347071583514099783080260303687635574837310195227765726681127982646420824295010845986984815618221258134490238611713665943600867678958785249457700650759219088937093275488069414316702819956616052060737527114967462039045553145336225596529284164859 
  487    002053388090349075975359342915811088295687885010266940451745379876796714579055441478439425051334702258726899383983572895277207392197125256673511293634496919917864476386036960985626283367556468172484599589322381930184804928131416837782340862422997946611909650924024640657084188911704312114989733059548254620123203285420944558521560574948665297741273100616016427104722792607802874743326488706365503080082135523613963039014373716632443531827515400410677618069815195071868583162217659137577 
  491    0020366598778004073319755600814663951120162932790224032586558044806517311608961303462321792260692464358452138492871690427698574338085539714867617107942973523421588594704684317718940936863543788187372708757637474541751527494908350305498981670061099796334012219959266802443991853360488798370672097759674134419551934826883910386965376782077393075356415478615071283095723014256619144602851323828920570264765784114052953156822810590631364562118126272912423625254582484725050916496945010183299389 
  499    002004008016032064128256513026052104208416833667334669338677354709418837675350701402805611222444889779559118236472945891783567134268537074148296593186372745490981963927855711422845691382765531062124248496993987975951903807615230460921843687374749498997995991983967935871743486973947895791583166332665330661322645290581162324649298597194388777555110220440881763527054108216432865731462925851703406813627254509018036072144288577154308617234468937875751503006012024048096192384769539078156312625250501 
  503    0019880715705765407554671968190854870775347912524850894632206759443339960238568588469184890656063618290258449304174950298210735586481113320079522862823061630218687872763419483101391650099403578528827037773359840954274353876739562624254473161033797216699801192842942345924453280318091451292246520874751491053677932405566600397614314115308151093439363817097415506958250497017892644135188866799204771371769383697813121272365805168986083499005964214711729622266401590457256461232604373757455268389662027833 

 ...
 
 2971    000336587007741501178054527095254123190844833389431167956916863009087849209020531807472231571861326152810501514641534836755301245371928643554358801750252440255806125883540895321440592393133625042073375967687647256815886906765398855604173678895994614607876135981151127566475934028946482665769101312689330191854594412655671491080444294850218781555031975765735442611915180074049141703130259171995960955907101985863345674856950521709861999326825984516997643890945809491753618310333221137664086166273981824301581958936385055536856277347694378996970716930326489397509256142712891282396499495119488387748232918209357118815213732749915853248064624705486368226186469202288791652642208010770784247728037697744867048131942107034668461797374621339616290811174688657017839111410299562436889936048468529114776169639851901716593739481656008078088185796028273308650286098956580276001346348030966004712218108381016492763379333557724671827667452036351396836082127229888926287445304611242006058566139347021204981487714574217435207001009761023224503534163581285762369572534500168293503870750589027263547627061595422416694715583978458431504543924604510265903736115785930663076405250757320767418377650622685964321777179400875126220127903062941770447660720296196566812521036687983843823628407943453382699427802086839447997307303938067990575563783237967014473241332884550656344665095927297206327835745540222147425109390777515987882867721305957590037024570851565129585997980477953550992931672837428475260854930999663412992258498821945472904745876809155166610568832043083136990912150790979468192527768428138673847189498485358465163244698754628071356445641198249747559744193874116459104678559407606866374957926624032312352743184113093234601144395826321104005385392123864018848872433524065971053517334230898687310669808145405587344328508919555705149781218444968024234264557388084819925950858296869740828004039044092898014136654325143049478290138000673174015483002356109054190508246381689666778862335913833726018175698418041063614944463143722652305621003029283069673510602490743857287108717603500504880511612251767081790642881184786267250084146751935375294513631773813530797711208347357791989229215752271962302255132951868057892965331538202625378660383709188825311342982160888589700437563110063951531470885223830360148098283406260518343991921911814203971726691349713901043419723998653651969033995287781891618983507236620666442275328172332547963648603163917872770111073712554695388757993941433860652978795018512285425782564792998990238976775496465836418714237630427465499831706496129249410972736452372938404577583305284416021541568495456075395489734096263884214069336923594749242679232581622349377314035678222820599124873779872096937058229552339279703803433187478963312016156176371592056546617300572197913160552002692696061932009424436216762032985526758667115449343655334904072702793672164254459777852574890609222484012117132278694042409962975429148434870414002019522046449007068327162571524739145069 

That’s, um, quite a reptend for 1/2971

The code, in all its compact goodness:

unit sub MAIN () ;


for ( 2..3000 ) {
    my ($real, $reptend) = (1/$_).base-repeating(10);
    $reptend.chars == $_ - 1  
        ??  printf "%5d    %s \n", $_, $reptend
        !!  next    ;
}


The Perl Weekly Challenge, that idyllic glade wherein we stumble upon the holes for these sweet descents, is now known as

The Weekly Challenge – Perl and Raku

It is the creation of the lovely Mohammad Sajid Anwar and a veritable swarm of contributors from all over the world, who gather, as might be expected, weekly online to solve puzzles. Everyone is encouraged to visit, learn and contribute at

https://theweeklychallenge.org