An algorithm weekly question 003: flop

problem:

There 100 reads the digital card 1 to 100, and sequentially arranged. Initially all the cards are on the back side up. Someone from the first two cards, every one the flop. Then 2, 4, 6, ..., 100 cards will become a side-up. Next, another person from the first three cards, the flop every two (the original back up, flip to face up; the original face up, flip to the back-up). Then again, there is a person from the first four cards, every three flop cards. Thus, starting from the n-th card, every n-1 card flop, flip until no cards.
An algorithm weekly question 003: flop
When all the cards are no longer seeking change, all the back up of the card number.

Ideas:

There are many ideas this question:

Ideas 1
i that is round, starting from 1, 99 to the end. And j index cards.
Every round according to the subject of cards one by one to find the meaning of the questions at the corresponding flip.

Thinking 2
i that is round, starting from 1, 99 to the end; and j is the index card.
Every round on all cards to meet the requirements of the flip.

3 ideas
cards only when an even number will flip back up.
The card is turned over timing: when the number of steps about face for the brand, which is not very easy to understand, illustrated.
Such as: 4 plate, the back up initially,
round 1, 2 plate from the start, step 2,4 plate is flipped right side up;
round 2, starting from the plate 3, step size 3,4 plate is not turning;
of 3, starting from the plate 4, steps 4,4 plate is flipped back up;
he would not be flipped

It can be seen that, when the step length is 2,4, 4 turning plate will occur, and the divisor are 2 and 4 4.

Such as: plate 6, is a back up initial,
round 1, beginning from the plate 2, in steps of 2,6 plate is flipped right side up;
round 2, starting from the plate 3, step size 3,6 plate is flipped back up;
of 3, 4 starting from the plate, a step size of 4,6 plate is not turning;
of 4, 5 starting from the plate, steps 5,6 plate is not turning;
of 5, 6 starting from the plate, a step size of 6,6 plate is flipped right side up;
he would not be flipped

You can see that when the step size is 2,3,6, 6 plate flip occurs, while the number 2,3,6 are about 6.
If this number is a count about all natural numbers, the number of bird offer number is an odd number, would eventually facing the back.

You can continue to be summarized:

For example:
12 number plate, number about 1,2,3,4,6,12, a total of six divisor, and ultimately face up;
16 number plate, number about 1,2,4,8,16, there are five common divisor, eventually is a rear facing;
25 plates, from about 1,5,25 number, a total number of about 3, is a back up eventually;
noted, all of the back-up card 4,16 25, which are square numbers.
So this question ultimately becomes all the 1-100 number to find out the square.

answer:

The following three ideas above are given PHP code and Golang

PHP

// 按顺序进行翻牌,i为牌下标,j为牌下标+步长
function flip1()
{
    $size = 100;
    $cards = array_fill(0, $size, 0); // 初始化数组

    // i为轮次
    for ($i = 1; $i <= $size; $i++) {
        // 如果当前的牌是正面,就翻过来;反之亦然。
        // 每轮步长增长为i+1,
        // 例如:
        // 第一轮起始下标是1,步长是2(=1+1),翻1,3,5...下标的牌
        // 第二轮起始下标是2,步长是3(=2+1),翻2,5,8...下标的牌
        // 以此类推
        for ($j = $i; $j < $size; $j += $i + 1) {
            $cards[$j] = !$cards[$j];
        }
    }
    output($cards);
}

// i为轮次,j为牌下标
// 第1轮:2,4,6...100的牌被翻转,对应的下标为1,2,3...99,(j+1)%(1+1)==0
// 第2轮:3, 6, 9...99的牌被翻转,对应的下标为2,5,8...98,(j+1)%(2+1)==0
// 以此类推,得到公式,(j+1)%(i+1)==0时,牌都会翻转
function flip2()
{
    $size = 100;
    $cards = array_fill(0, $size, 0); // 初始化数组
    for ($i = 1; $i < $size; $i++) {
        for ($j = 1; $j < $size; $j++) {
            if (($j + 1) % ($i + 1) == 0) {
                $cards[$j] = !$cards[$j];
            }
        }
    }
    output($cards);
}

// 当牌i翻转为偶数次时,即为背面朝上
// 当j为i的约数时,会触发一次i的翻转
// 比如:牌4,会在约数为1,2,4时被翻转
// 但所有的牌都是从约数为2开始翻,所以排除掉约数1的情况
// 此时,4号牌只翻转了2次,符合偶数次翻转的情况,所以其最终是背面朝上
function flip3()
{
    $size = 100;
    $tmp = array();

    // i为牌面,数字为1-100的100张牌
    for ($i = 1; $i <= $size; $i++) {
        $flag = false;

        // j为步长
        for ($j = 2; $j <= $size; $j++) {
            if ($i % $j == 0) {
                $flag = !$flag;
            }
        }

        if ($flag == false) {
            $tmp[] = $i;
        }
    }
    echo implode(' ', $tmp) . "\n";
}

function output($cards)
{
    foreach ($cards as $key => $val) {
        if (!$val) {
            echo $key + 1;
            echo " ";
        }
    }
    echo "\n";
}

flip1();
flip2();
flip3();

Export

1 4 9 16 25 36 49 64 81 100 
1 4 9 16 25 36 49 64 81 100 
1 4 9 16 25 36 49 64 81 100

Golang

package main

import "fmt"

var size = 100 // 牌数

func main() {
    Flip1()
    Flip2()
    Flip3()
}

// 初始化数据
func initCards() []bool {
    var cards []bool // 存放每张牌的状态
    for i := 0; i < size; i++ {
        cards = append(cards, false)
    }
    return cards
}

// 翻牌算法1
func Flip1() {
    cards := initCards()
    for i := 1; i < size; i++ {
        for j := i; j < size; j += i + 1 {
            cards[j] = !cards[j]
        }
    }
    PrintCards(cards)
}

// 翻牌算法2
func Flip2() {
    cards := initCards()
    for i := 1; i < size; i++ {
        for j := i; j < size; j++ {
            if (j+1)%(i+1) == 0 {
                cards[j] = !cards[j]
            }
        }
    }
    PrintCards(cards)
}

// 翻牌算法3
func Flip3() {
    var cards []int
    for i := 1; i <= size; i++ {
        flag := false
        for j := 2; j <= size; j++ {
            if i%j == 0 {
                flag = !flag
            }
        }
        if flag == false {
            cards = append(cards, i)
        }
    }
    fmt.Println(cards)
}

// 输出牌面
func PrintCards(cards []bool) {
    var results []int
    for i := 0; i < size; i++ {
        if cards[i] == false {
            results = append(results, i+1)
        }
    }
    fmt.Println(results)
}

Export

[1 4 9 16 25 36 49 64 81 100]
[1 4 9 16 25 36 49 64 81 100]
[1 4 9 16 25 36 49 64 81 100]

Guess you like

Origin blog.51cto.com/ustb80/2421507