The Bear's Den

Enter at your own risk

A Bigger Omega

Task 1: Make it Bigger

Submitted by: Mohammad Sajid Anwar


You are given a given a string number and a character digit.

Write a script to remove exactly one occurrence of the given character digit from the given string number, resulting the decimal form is maximised.

Example 1

Input: $str = "15456", $char = "5"
Output: "1546"

Removing the second "5" is better because the digit following it (6) is
greater than 5. In the first case, 5 was followed by 4 (a decrease),
which makes the resulting number smaller.

Example 2

Input: $str = "7332", $char = "3"
Output: "732"

Example 3

Input: $str = "2231", $char = "2"
Output: "231"

Removing either "2" results in the same string here. By removing a "2",
we allow the "3" to move up into a higher decimal place.

Example 4

Input: $str = "543251", $char = "5"
Output: "54321"

If we remove the first "5", the number starts with 4. If we remove the
second "5", the number still starts with 5. Keeping the largest possible
digit in the highest place value is almost always the priority.

Example 5

Input: $str = "1921", $char = "1"
Output: "921"

Solution

There is an easy way to solve this task: Remove occurrences of the digit $char from $str and take the maximum from the resulting list.

The Perl solution follows this approach.

However, a tacit verb in J cannot use named variables. All my attempts to implement this approach in J therefore appeared rather ugly and there should be a different approach that can be better implemented in a pure functional way.

When the given digit is immediately followed by a larger digit within the given number, the removal of the leftmost occurrence of this digit produces the largest result. Otherwise, if the digit is not immediately followed by a larger digit anywhere within the given number, then the removal of the rightmost occurrence of this digit produces the largest result.

Perl

Returns undef if the digit is not found in the number.

use strict;
use warnings;
use List::Gather;
use Math::Prime::Util qw(todigits fromdigits vecmax);

sub bigger {
    my ($c, @tail, @head) = (shift, todigits(shift, 10));
    vecmax gather {
        while (@tail) {
            my $d = shift @tail;
            take fromdigits([@head, @tail], 10) if $d == $c;
            push @head, $d
        }
    };
}

See the full solution to task 1.

J

Find the index of the to-be-removed element and remove it under todigits conversion.

This returns the unmodified number if the digit is not found.

remove =: {. , >:@[ }. ]           NB. remove item at index x from y
shl =: 1&(|.!.0)                   NB. shift left, insert zero
idx =: i:~ <. 1 i.~ = *. shl@] > ] NB. find first index of x in y preceding a larger number
                                   NB. or the index of the last ocurrence of x in y 
bigger =: idx remove ]
todigits =: 10&#.^:_1              NB. convert number to list of decimal digits

echo 5 bigger&.(a:`todigits) 15456
echo 5 bigger&.(a:`todigits) 543251

See the full solution.

Task 2: Big and Little Omega

Submitted by: Roger Bell_West


You are given a positive integer $number and a mode flag $mode. If the mode flag is zero, calculate little omega (the count of all distinct prime factors of that number). If it is one, calculate big omega (the count of all prime factors including duplicates).

Example 1

Input: $number = 100061
       $mode = 0
Output: 3

Prime factors are 13, 43, 179. Count is 3.

Example 2

Input: $number = 971088
       $mode = 0
Output: 3

Prime factors are 2, 2, 2, 2, 3, 20231. Count of distinct numbers is 3.

Example 3

Input: $number = 63640
       $mode = 1
Output: 6

Prime factors are 2, 2, 2, 5, 37, 43. Count including duplicates is 6.

Example 4

Input: $number = 988841
       $mode = 1
Output: 2

Example 5

Input: $number = 211529
       $mode = 0
Output: 2

Solution

With the prime factorization \(n = \sum_{i=1}^k p_i^{e_i}\) where \(p_i\) are distinct prime numbers and \(e_i > 0\), the “Little” and “Big” Omega functions are special cases of the form \(\omega(n, m) = \sum_{i=1}^k e_i^m\) with \(m \in \{0, 1\}\).

Permitting any real value for \(m\) leads to a generalized solution for this task.

Perl

use strict;
use warnings;
use Math::Prime::Util 'factor_exp';
use List::Util 'sum';

sub omega {
    my $exp = shift;
    sum map $_->[1] ** $exp, factor_exp(shift);
}

See the full solution to task 2.

J

omega =: [: +/ [ ^~ [: {: 2&p:@]

echo 0 omega 100061
echo 1 omega 63640
echo 2 omega 1944810000
echo _1 omega 1944810000
echo 0.5 omega 1944810000

See the full solution.