在某些规则下动态创建数组

时间:2016-10-25 19:19:51

标签: algorithm

我需要创建具有遵循这些模式的特定值/属性的数组。

不幸的是,我的数学知识并没有让我找到这种模式。

这是一个应该在(从下到上)输出的数组的示例n = 1,2和3(沿着每条边计算红框)。

enter image description here

所有红色和绿色方块都应该分配一些值,而所有白色方块都需要未定义(或空,null,某些东西)。

创建数组,如何动态分配它们各自的红/绿/白值?

    for (var x = 0; x < n * 4 - 1; x++)
    {
        for (var y = 0; y < n * 4 - 1; y++)
        {
            board[x][y] = green, red or white?;
        }
    }

PS:如果不明显,该模式会创建“红色”边长为n的六边形。

3 个答案:

答案 0 :(得分:1)

每个六边形由三部分组成(从上到下):

  1. 上半部分由覆盖整个宽度的绿线终止

  2. 一条红色方格线

  3. 下半部分以绿线覆盖整个宽度

  4. 上半部分和下半部分是自身的镜像,在2中的线条上反射。

    对于给定的 n ,总行数 2 n - 1 + 2 n 2 n - 1 术语是由红线引起的:它们中有 2 n ,但其中两个(最长的)是一个在彼此之上。 2 n 术语是由绿线引起的(它是红线的数量+ 1)。

    这是绘制上半部分的Python代码(开头的第1项):

    def print_hex_upper_half(n):
        num_lines = 2 * (n - 1) + 1
        width = (2 * n - 1) + 2 * n
        for i in range(1, num_lines + 1):
            if i % 2 == 1:
                s = n - i / 2 - 1
                print ' ' * s + 'G' * (width - 2 * s) + ' ' * s
            else:
                s = n - i / 2 + 1
                rw = (width - 2 * s + 1) / 2
                print ' ' * s + ' '.join('R' * rw) + ' ' * s
    

    这里是运行时:

    >>> print_hex_upper_half(4)
       GGGGGGGGG   
        R R R R    
      GGGGGGGGGGG  
       R R R R R   
     GGGGGGGGGGGGG 
      R R R R R R  
    GGGGGGGGGGGGGGG
    
    >>> print_hex_upper_half(3)
      GGGGGGG  
       R R R   
     GGGGGGGGG 
      R R R R  
    GGGGGGGGGGG
    
    >>> print_hex_upper_half(2)
     GGGGG 
      R R  
    GGGGGGG
    
    >>> print_hex_upper_half(1)
    GGG
    

    中间线很容易,下半部分是反射,所以这只是操纵指数的问题。

    以下是代码的详细说明:

    • 由于上述原因,上半部分的行数为 2(n - 1)+ 1 ,宽度在上面给出。

    • 奇数行为绿色,偶数行为红色。

    • 出于同样的原因,绿色行以 n - i / 2 - 1 空格开始和结束。其余的都是绿色的。

    • 同样,由于上面给出的相同原因,红色行以 i / 2 + 1 空格开始和结束。其余的红色点缀着空间。如果我们从这个数量的宽度中减去,加1,除以2,我们得到红色块的数量。

答案 1 :(得分:1)

如问题中所述,所有关于在问题中找到模式的问题都可以将问题分解为一系列较小的问题。

n

的图片尺寸

一旦我们看到参数n与六边形的边长相关, 我们可以发现图片中最大数量的红色方块将是
nRedsMax n = 2 * n - 1
现在,图片中的绿线总是比红色条带长2个像素 下方(左侧1个像素,右侧1个)。 这导致了 nGreensMax n = nRedsMax n + 2
从样本pixture,我们看到最长的绿线填充整行 的图片。因此,
dimX n = nGreensMax n
我们还可以看到,图片是正方形。所以
dimY n = dimX n
把它们放在一起并简化术语,我们发现,图片大小 由n是:
dim n = 4 * n - 1

找到n

的像素值x,y

基本上,图片是两张图片,垂直交错。绿线为一条,线条为红色,另一条为绿色。所以我们可以得出结论,我们有2个案例,我们可以单独处理。

我们还看到,图片的上半部分和图片的下半部分与中轴对称。

因此,对于行y中的像素的计算,我们总是使用
y' = mirrorUp n y
这适用于两种类型的线(红线和绿线)。

绿线

图片在x方向上缩放了2倍。因此,对于显示长度为n的六边形的图片,红色和白色条带的长度为2 * n。并且上面的绿线从红色条带的左侧开始1个像素,因此比下面的红色条带长1个像素 nGreen n y = 2 * n + 1 + 2 * div (mirrorUp n y) 2

红线

红线也在图片的中心,对于每个逻辑红点,我们使用R - 两个字符。如果
nRed n y = n + div (mirrorUp y) 2
给出y行中的红色像素数,因此,红色字符串的长度为2 * nRed n y

将绿色和红色条带对齐

条带未使用的像素数量为
dim n - length strip 为了使条带成一排,我们需要左边一半,右边一半。

这导致以下代码,其编写使得可以容易地找到上述步骤。

module Hexagon(picture,color) where 
import Data.List.Split(chunksOf)

-- The 3 possible values of the output matrix.
data Color = WHITE | RED | GREEN deriving(Eq,Show)

-- The size of the output matrix.
-- n -> Array[dim n,dim n]
dim n = 4 * n - 1

-- classify the type of line by index. 
-- There are Green lines (those with greens)
-- and red lines (those with the reds)
rowType :: Int -> Color
rowType y | mod y 2 == 0 = GREEN
rowType y | mod y 2 == 1 = RED

-- y-symmetry of picture - mirror y of lower half
-- to y of upper half
mirrorUp :: Int -> Int -> Int
mirrorUp n y 
    | y < div (dim n) 2 = y
    | otherwise = dim n - y - 1

-- Number of green elements by n and y
nGreen :: Int -> Int -> Int
nGreen n y = n * 2 + 1 + 2 * div (mirrorUp n y) 2

-- Number of red elements by n and y
nRed :: Int -> Int -> Int
nRed n y = n + div (mirrorUp n y) 2

-- Compute the color of an element by n,x,y
color :: Int -> Int -> Int -> Color
color n x y 
    | rowType y == GREEN && (x < div (dim n - nGreen n y) 2)  
        = WHITE
    | rowType y == GREEN && x >= (div (dim n - nGreen n y) 2 + nGreen n y)
        = WHITE
    | rowType y == GREEN = GREEN
    | rowType y == RED =
        if x < border || x > dim n - border then WHITE
        else 
            case mod (x - border) 2 of
                0 -> RED
                1 -> WHITE
        where
            border = div (dim n - redStrip) 2
            redStrip = 2 * nRed n y - 1

-- color 2 output character
col2char :: Color -> Char
col2char WHITE = '_'
col2char RED = 'R'
col2char GREEN = 'G'            

-- create the ASCII picture of the hexagon for parameter n
picture :: Int -> [Char]
picture n =
    (unlines . chunksOf (dim n)) values
    where 
        values = 
            [col2char (color n x y) | y <- [0,1..dim n - 1], x <- [0,1..dim n - 1] ]

-- Usage Example:
-- putStrLn $ picture 3

答案 2 :(得分:1)

使用其他优秀答案的输入,这是我实施的最终版本:

var $log = $("#log");

var size = 3;
var dimension = size * 4 - 1;

for (var x = 0; x < dimension; x++)
{
	var isUpperHalf = x < size * 2;
	var isRedRow = x % 2 === 1;
	var nextRed = true;

	for (var y = 0; y < dimension; y++)
	{
		var color = " ";
		
		if (isUpperHalf)
		{
			padding = size - Math.floor(x / 2) - 1;
		}
		else
		{
			padding = Math.ceil(x / 2) - size;
		}
		
		if (isRedRow && y > padding && y < dimension - padding)
		{
			if (nextRed)
			{
				color = "r";
			}
			nextRed = !nextRed;
		}
		else if (!isRedRow && y >= padding && y < dimension - padding)
		{
			color = "g";
		}

		$log.append("<span class='" + color + "'>&nbsp;</span>");
	}
	
	$log.append("<br/>");
}
#log {
	font-family: courier;
}
span {
	width: 20px;
	display: inline-block;
}
.g {
	background-color: green;
}
.r {
	background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="log">

</div>