7
\$\begingroup\$

Specifications

For this challenge, you will be given a matrix of some sort in any reasonable format for a 2-D array. For each row except the last, in order from top (first) to bottom (last), rotate the row below it by x to either direction (you choose a consistent direction to use) where x is the first element in the current row.

Reference

A reference implementation in Python can be found here

Example

Let's walk through an example. Take the following matrix for example:

1 5 8
4 7 2
3 9 6

Let's say we're rotating right. First we rotate [4 7 2] to the right by 1 because the first element of [1 5 8] is 1. Thus, we get [2 4 7] as the second row. The matrix is now like this:

1 5 8
2 4 7
3 9 6

Then, we rotate [3 9 6] to the right by 2 because the first element of the second row is 2. Thus we get:

1 5 8
2 4 7
9 6 3

Challenge

Implement the above

Test Cases

Test cases are given as a list of lists in Python style.

Input -> Output
[[6, 7, 10, 1, 10, 7], [7, 3, 7, 8, 9, 2], [6, 8, 3, 9, 3, 1], [6, 3, 8, 6, 4, 1], [7, 5, 2, 9, 7, 2], [2, 10, 9, 9, 7, 9], [8, 8, 10, 10, 8, 4]] -> [[6, 7, 10, 1, 10, 7], [7, 3, 7, 8, 9, 2], [1, 6, 8, 3, 9, 3], [1, 6, 3, 8, 6, 4], [2, 7, 5, 2, 9, 7], [7, 9, 2, 10, 9, 9], [4, 8, 8, 10, 10, 8]]
[[8, 10, 4, 3, 9, 4, 6], [8, 8, 8, 8, 6, 7, 5], [6, 2, 2, 4, 8, 9, 6], [1, 7, 9, 9, 10, 7, 8]] -> [[8, 10, 4, 3, 9, 4, 6], [5, 8, 8, 8, 8, 6, 7], [2, 4, 8, 9, 6, 6, 2], [7, 8, 1, 7, 9, 9, 10]]
[[6, 2, 4, 4, 4], [5, 9, 10, 5, 4], [3, 5, 7, 2, 2], [1, 5, 5, 10, 10], [8, 2, 3, 2, 1], [3, 3, 9, 5, 10], [9, 5, 9, 7, 2]] -> [[6, 2, 4, 4, 4], [4, 5, 9, 10, 5], [5, 7, 2, 2, 3], [1, 5, 5, 10, 10], [1, 8, 2, 3, 2], [10, 3, 3, 9, 5], [9, 5, 9, 7, 2]]
[[3, 6, 3, 7, 4], [8, 8, 1, 5, 8], [7, 5, 1, 9, 4], [3, 9, 10, 8, 6]] -> [[3, 6, 3, 7, 4], [1, 5, 8, 8, 8], [4, 7, 5, 1, 9], [9, 10, 8, 6, 3]]
[[5, 6, 1, 2, 6], [1, 10, 10, 1, 4], [6, 2, 7, 1, 7], [9, 5, 8, 6, 3], [4, 5, 1, 2, 1], [8, 6, 1, 1, 3]] -> [[5, 6, 1, 2, 6], [1, 10, 10, 1, 4], [7, 6, 2, 7, 1], [6, 3, 9, 5, 8], [1, 4, 5, 1, 2], [3, 8, 6, 1, 1]]
[[10, 1, 2], [9, 9, 10], [2, 4, 7]] -> [[10, 1, 2], [10, 9, 9], [7, 2, 4]]
[[4, 5, 6], [6, 9, 4], [9, 3, 2], [3, 5, 9], [5, 5, 3], [9, 1, 4]] -> [[4, 5, 6], [4, 6, 9], [2, 9, 3], [5, 9, 3], [5, 3, 5], [1, 4, 9]]
[[8, 7, 6, 5], [9, 8, 6, 6], [7, 9, 7, 10]] -> [[8, 7, 6, 5], [9, 8, 6, 6], [10, 7, 9, 7]]
[[10, 2, 8, 8, 1], [2, 10, 1, 4, 10], [3, 2, 5, 3, 8], [5, 1, 8, 1, 8], [6, 1, 3, 1, 2], [7, 9, 1, 1, 2]] -> [[10, 2, 8, 8, 1], [2, 10, 1, 4, 10], [3, 8, 3, 2, 5], [8, 1, 8, 5, 1], [3, 1, 2, 6, 1], [1, 1, 2, 7, 9]]
[[9, 1, 3, 2, 7], [3, 8, 10, 3, 3], [8, 10, 7, 9, 5], [8, 1, 4, 9, 9], [6, 8, 4, 10, 10], [4, 7, 6, 2, 2], [8, 5, 3, 7, 6]] -> [[9, 1, 3, 2, 7], [8, 10, 3, 3, 3], [7, 9, 5, 8, 10], [9, 9, 8, 1, 4], [8, 4, 10, 10, 6], [6, 2, 2, 4, 7], [6, 8, 5, 3, 7]]

Generate more testcases here

\$\endgroup\$
  • 1
    \$\begingroup\$ we rotate [4 7 2] to the right by 1 ... we get [2 7 4] Wait, what? Shouldn't it be [2 4 7]? Or am I misunderstanding "rotation"? \$\endgroup\$ – totallyhuman Sep 7 '17 at 21:58
  • 1
    \$\begingroup\$ For each row except the last Shouldn't that be except the first? \$\endgroup\$ – totallyhuman Sep 7 '17 at 22:00
  • \$\begingroup\$ @icrieverytim rotate the row below it technically this is inconsistent with my title but eh \$\endgroup\$ – HyperNeutrino Sep 7 '17 at 22:03
  • 2
    \$\begingroup\$ Are we guaranteed that the matrix is positive integers and that the matrix has at least two rows? \$\endgroup\$ – Giuseppe Sep 7 '17 at 22:14
  • 1
    \$\begingroup\$ Since x can be larger than the length of the row below (according to the test cases), what exactly is [2, 5, 8] rotated by 4? The second test case says it's [2, 5, 8] which doesn't make a lot of sense to me... \$\endgroup\$ – totallyhuman Sep 7 '17 at 22:20

10 Answers 10

5
\$\begingroup\$

Husk, 4 bytes

G(ṙ←

Try it online!

Rotates rows to the left.

Explanation

G in Husk is scanl (or cumulative reduce from left, as some languages call it). When given a function of type x->x->x (like in this case) it can use as starting value the first element of the list.

( is needed here to combine the following two functions into a single one.

is "rotate to the left" and takes a number and a list as arguments.

returns the first element of a list.

\$\endgroup\$
3
\$\begingroup\$

Jelly, 6 5 bytes

ṙ@Ḣð\

Try it online!

Rotates to the left.

Saved a byte thanks to @Jonathan Allan.

Explanation

ṙ@Ḣð\  Input: array of arrays M
   ð\  Cumulative reduce over each array using
ṙ@       Rotate the RHS array using each in the LHS array
  Ḣ      Head
\$\endgroup\$
  • \$\begingroup\$ You can dump the \$\endgroup\$ – Jonathan Allan Sep 7 '17 at 22:48
  • \$\begingroup\$ @JonathanAllan Thanks. Isn't ɓ supposed to work here, as in ṙḢɓ\. \$\endgroup\$ – miles Sep 7 '17 at 22:52
  • \$\begingroup\$ Ah, that actually may require a code change to reduce_cumulative; it would make sense to do so... \$\endgroup\$ – Jonathan Allan Sep 7 '17 at 23:00
3
\$\begingroup\$

C++, 187 149 bytes

  • 38 bytes thanks to Karl Napf

Output is done by the reference type parameter The parameter's type have to be a std::vector<std::vector<int>> type

auto r=[](auto&a){for(int i=1,j,v;i<a.size();++i){v=a[i-1][0]%a[i].size();for(j=0;j<v;++j){a[i].insert(a[i].begin(),a[i].back());a[i].pop_back();}}};

Trying to do as #define A a[i] and replacing all occurences of a[i] by A will result with same byte count code

Code to help for the test :

//Shift operator overload
std::ostream& operator<<(std::ostream& os, std::vector<std::vector<int>>& v) {
    os << "{\n";
    for (auto&a : v) {
        os << "\t{ ";
        for (auto&b : a) {
            os << b << ' ';
        }
        os << "},\n";
    }
    return os << "}\n";
}

And in the main function

std::vector<std::vector<int>> t{
    {1,5,8},
    {4,7,2},
    {3,9,6}
};

std::cout << t;

r(t);

std::cout << t;
\$\endgroup\$
  • 1
    \$\begingroup\$ You can drop the #include and std::vector<... declarations by using an unnamed generic lambda [](auto&a){...} and demanding the input to be like vector<vector<int>> as I did in my challenges, e.g. codegolf.stackexchange.com/questions/100205/… \$\endgroup\$ – Karl Napf Sep 8 '17 at 16:08
2
\$\begingroup\$

Haskell, 84 59 45 bytes

Shifts to the left (now using Leo's approach):

scanl1(\a r->(drop<>take$a!!0`mod`length r)r)

Try it online!

\$\endgroup\$
  • \$\begingroup\$ 59 bytes: Try it online! \$\endgroup\$ – Laikoni May 4 '18 at 23:36
  • \$\begingroup\$ @Laikoni: Damn that's so much nicer and saves a whole lot of bytes, thanks a lot! \$\endgroup\$ – ბიმო May 5 '18 at 0:23
1
\$\begingroup\$

Python 2, 65 bytes

l=input();K=0
for i in l:g=-K%len(i);e=i[g:]+i[:g];print e;K=e[0]

Try it online!

Python 2, 55 bytes (possibly broken)

If this version is found to fail for some test cases, I can assure you the above works. I am currently half-asleep, so feel free to remove this version in case it is invalid by editing.

l=input();K=0
for i in l:e=i[-K:]+i[:-K];print e;K=e[0]

Try it online!

\$\endgroup\$
  • \$\begingroup\$ You need to add modulo somewhere in there. The rotation numbers are sometimes longer than the lengths. \$\endgroup\$ – totallyhuman Sep 7 '17 at 22:15
  • \$\begingroup\$ @icrieverytim I think it's fixed \$\endgroup\$ – Mr. Xcoder Sep 7 '17 at 22:17
  • \$\begingroup\$ ...Actually, the test cases don't reflect that, which is in turn because the reference implementation doesn't use modulo. I'll ask OP whether it's needed. \$\endgroup\$ – totallyhuman Sep 7 '17 at 22:19
1
\$\begingroup\$

05AB1E, 9 bytes

vyNFÁ}=нƒ

Try it online!

vy        # For each row:
  NFÁ}    #   Rotate this row N times (initially 0)
      =   #   Print without popping
       н  #   Get the head
        ƒ #   Assign that to N 
\$\endgroup\$
0
\$\begingroup\$

Perl 5, 41 + 1 (-a) = 42 bytes

push@F,shift@F for 1..$r;say"@F";$r=$F[0]

Try it online!

Rotates to the left. Takes the input as lines of space separated integers.

How?

Remove an element from the left end of the list, put it on the right end as many times as we should rotate ($r). Since $r starts at undef (equivaltent to 0 in this usage), nothing happens to the first line. Output the list. Save the first element of the list in $r so we can rotate that many times on the next line.

\$\endgroup\$
0
\$\begingroup\$

Pyth, 11 bytes

VQ=ZhJ.>NZJ

Try it here!

Explanation

  • VQ - For each list in the matrix input:

    • =Z - Assign Z to the value of the below statement. Its initial value is 0, so that helps us with the first row.

    • h - The first element of ...

    • J.>NZ - ... The current list, cyclically rotated by Z places, and assigned to a variable J.

    • J - Print J.

\$\endgroup\$
0
\$\begingroup\$

R, 77 bytes

function(B){for(i in 2:nrow(B))B[i,]=rep(B[i,],sum(B))[1:ncol(B)+B[i-1,1]]
B}

Try it online!

Rotates rows to the right.

Replicates each row of B sum(B) times (creating a huge vector), then grabs the appropriate values from that replicated vector to put into the correct row.

I also wrote a function in the header that converts from the python matrix format to R matrices.

\$\endgroup\$
0
\$\begingroup\$

APL (Dyalog), 14 bytes

Anonymous tacit prefix function. Takes list of lists as argument and prints rows on separate lines with the numbers in each row separated by single spaces. Rotates left (although the explanation mentions how rotate right).

{⎕←⍺⌽⍨⊃⍵}/0,⍨⌽

Try it online!

 reverse the argument (because reduction is right-to-left)

0,⍨ append a zero (for initial rotation of zero steps)

{}/ reduce by the following anonymous lambda, where is the element on the left and on the right (the reduction goes right-to-left

 pick the first of the right argument

⍺⌽⍨ rotate the left argument to the left* that many steps

⎕← output to STDOUT with a trailing line-break


* To rotate right, insert a - to the right of . This will negate the rotation amount.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.