Problem of the Day
A new programming or logic puzzle every Mon-Fri

Spiral Line

Given an integer x, output a spiral design that has that many lines in it. For example:

x = 5
*****
....*
***.*
*...*
*****

x= 11

***********
..........*
*********.*
*.......*.*
*.*****.*.*
*.*...*.*.*
*.*.***.*.*
*.*.....*.*
*.*******.*
*.........*
***********

Permalink: http://problemotd.com/problem/spiral-line/

Comments:

  • Anonymous - 10 years, 5 months ago

    I did it :D.. was a harder one tbh.. nvm here is a haskell solution

    spiral :: Int -> IO()
    spiral x = printList $ spiral' x '*'
    
    
    
    printList :: [String] -> IO ()
    printList [] = putStrLn ""
    printList (x:xs) = putStrLn x >> printList xs
    
    
    spiral' :: Int -> Char -> [String]
    spiral' i c
        | i <= 0 = []
        | i < 3 = [fill]
        | otherwise = fill:(final++[fill])
            where
                fill = [c | y <- [1..i]]
                next = correct rec
                rec = spiral' (i-2) o
                correct = map (([c] ++) . (++ [c]))
                correctFst = o:(tail fst')
                fst' = head next
                rest = tail next
                final = (correctFst) : rest
                o = if c == '*' then '.' else '*'
    
    
    

    print list ist just there to show the printed list

    now i can finally go to bed :D

    reply permalink

  • mf - 10 years, 5 months ago

    another Haskell solution

    module Main where
    import Data.List (intersperse)
    
    type Dimension = (Int,Int)
    type Array = (Dimension, Int -> Int -> Char)
    type ArrayTransformer = Array -> Array
    
    main :: IO ()
    main = putStrLn $ renderArray $ spiral 11
    
    spiral :: Int -> Array
    spiral 1 = base
    spiral n = addLine . rot90 . addCorner $ spiral (n-1)
    
    base :: Array
    base = ((1,1),fn)
      where
         fn 1 1 = '*'
         fn l c = error $ show ("basefun out of Range",(l,c))
    
    addCorner :: ArrayTransformer
    addCorner ((lines,cols),fn) = ((lines,cols+1),fn')
      where
         fn' 1 1 = '*'
         fn' _ 1 = '.'
         fn' l c = fn l (c -1)
    
    addLine :: ArrayTransformer
    addLine ((lines,cols),fn) = ((lines+1,cols),fn')
      where
         fn' 1 _ = '*'
         fn' l c = fn (l-1) c
    
    rot90 :: ArrayTransformer
    rot90 ((lines,cols),fn) = ((cols,lines),fn')
      where
        fn' l c =  fn (lines-c+1) l
    
    renderArray :: Array -> String
    renderArray ((lines,cols),fn) = concat $ intersperse "\n" spiralLines
      where
        spiralLines :: [String]
        spiralLines = map makeLine [1..lines]
        makeLine :: Int -> String
        makeLine l = map (fn l) [1.. cols]
    

    reply permalink

  • David - 10 years, 5 months ago

    I have spent way too much time messing around with this...

    reply permalink

  • David - 10 years, 4 months ago

    I haven't touched this in most of the past week. I think I'll just post the crap I have at this point. No debug cleanup even.

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    #define true 1
    #define false 0
    #define debug 1
    
    #define Uint32  unsigned int
    
    #define hDirIndex 0
    #define vDirIndex 1
    
    //These are to follow the convention of the spiral, not of a coordinate system
    //[0][x] for horizontal direction
    //[1][x] for vertical direction
    signed char dir[2][4] = {{1,0,-1,0},
                                {0,1,0,-1}};
    
    void spiralMove(int* hIndexIn, int* vIndexIn, int direction, int steps) {
        *hIndexIn += dir[hDirIndex][direction] * steps;
        *vIndexIn += dir[vDirIndex][direction] * steps;
        return;
    }
    
    bool edgeCheck(/*hIndex, vIndex, direction, size*/)
    {
        //check vertical against direction
        //check horizontal against direction
    
        return true;
    }
    
    bool lineCheck()
    {
        return true;
    }
    
    void spiralLine(int x) {
        char outputLine[x];
        char spiralMatrix[x][x];    //(vertical)(horizontal)
        bool spiralOn = false;
        char currentDir = 0;
        int currentVertIndex = 1;
        int currentHoriIndex = 0;
        int topBound = 0, rightBound = x, bottomBound = x, leftBound = 0;
    
        //Generate the "empty" array
        for(int verticalIndex = 0; verticalIndex < x; verticalIndex++) {
            for(int horizontalIndex = 0; horizontalIndex < x; horizontalIndex++) {
                spiralMatrix[verticalIndex][horizontalIndex] = '*';
            }
        }
        //Create the actual spiral
        if(x > 2) {
            spiralOn = true;
            spiralMatrix[currentVertIndex][currentHoriIndex] = '.';
        }
        else {
            return;
        }
        int failsafe = 0;
        while(spiralOn) {
            while((currentHoriIndex + 2 < x) & (spiralMatrix[currentVertIndex+2*dir[vDirIndex][currentDir]][currentHoriIndex+2*dir[hDirIndex][currentDir]] != '.') & spiralOn)  {  //Go right
                //TODO: check that we are inside the last spiral
                printf("%i, %i\n", currentHoriIndex, currentVertIndex);
                currentHoriIndex += 1;
                spiralMatrix[currentVertIndex][currentHoriIndex] = '.';
            }
            if(currentVertIndex + 2 < x || (spiralMatrix[currentVertIndex+dir[vDirIndex][currentDir]][currentHoriIndex+dir[hDirIndex][currentDir]] != '.')) {
                //TODO: check that we are inside the last spiral
                currentDir += 1;
            }
            else {
                printf("Debug: Break should end the loop\n");
                spiralOn = false;
                break;
            }
            while((currentVertIndex + 2 < x) & (spiralMatrix[currentVertIndex+2*dir[vDirIndex][currentDir]][currentHoriIndex+2*dir[hDirIndex][currentDir]] != '.') & spiralOn) {  //Go down
                //TODO: check that we are inside the last spiral
                printf("%i, %i\n", currentHoriIndex, currentVertIndex);
                currentVertIndex += 1;
                spiralMatrix[currentVertIndex][currentHoriIndex] = '.';
            }
            if(currentHoriIndex - 2 > 0 || (spiralMatrix[currentVertIndex+dir[vDirIndex][currentDir]][currentHoriIndex+dir[hDirIndex][currentDir]] != '.')) {
                //TODO: check that we are inside the last spiral
                currentDir += 1;
            }
            else {
                printf("Debug: Break should end the loop\n");
                spiralOn = false;
                break;
            }
            while((currentHoriIndex - 2 >= 0) & (spiralMatrix[currentVertIndex+2*dir[vDirIndex][currentDir]][currentHoriIndex+2*dir[hDirIndex][currentDir]] != '.') & spiralOn) {  //Go left
                printf("%i, %i\n", currentHoriIndex, currentVertIndex);
                currentHoriIndex -= 1;
                spiralMatrix[currentVertIndex][currentHoriIndex] = '.';
            }
            if(currentVertIndex - 2 > 0 || (spiralMatrix[currentVertIndex+dir[vDirIndex][currentDir]][currentHoriIndex+dir[hDirIndex][currentDir]] != '.')) {
                currentDir += 1;
            }
            else {
                printf("Debug: Break should end the loop\n");
                spiralOn = false;
                break;
            }
            while((currentVertIndex - 2 >= 0) & (spiralMatrix[currentVertIndex+2*dir[vDirIndex][currentDir]][currentHoriIndex+2*dir[hDirIndex][currentDir]] != '.') & spiralOn) {  //Go up
                printf("%i, %i\n", currentHoriIndex, currentVertIndex);
                currentVertIndex -= 1;
                spiralMatrix[currentVertIndex][currentHoriIndex] = '.';
            }
            if(currentHoriIndex + 2 < x || (spiralMatrix[currentVertIndex+dir[vDirIndex][currentDir]][currentHoriIndex+dir[hDirIndex][currentDir]] != '.')) {
                currentDir += 1;
                currentDir %= 4;
            }
            else {
                printf("Debug: Break should end the loop\n");
                spiralOn = false;
                break;
            }
            //check if we continue
            if(failsafe++ == 5)
            {
                printf("Debug: We hit the failsafe\n");
                spiralOn = false;   //At the moment I just want to make sure I exit the while loop
            }
        }
        for(int verticalIndex = 0; verticalIndex < x; verticalIndex++) {
            for(int horizontalIndex = 0; horizontalIndex < x; horizontalIndex++) {
                outputLine[horizontalIndex] = spiralMatrix[verticalIndex][horizontalIndex];
            }
    #if debug
            printf("%s\n", outputLine);
    #endif
        }
    }
    
    int main(void) {
        spiralLine(11);
        return 0;
    }
    

    It has a but with the last turn being right next to a previous line if the size is inconvenient. I had intended to make a more generic function for advancing in the current direction to save on if/else cases, but got busy.

    reply permalink

Content curated by @MaxBurstein