-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bonus task - Console Function Plotter #8
Comments
Коментирайте взаимно решенията си. |
import System.Process
import Control.DeepSeq (deepseq)
import Control.Concurrent (threadDelay)
-- variables to manipulate output
defaultColourMap = "░▒▓█"
stepBetweenPoints = 0.05
widthFrom = -1
widthTo = 1
heightFrom = -1.5
heightTo = 1.5
shadePixelEpsilon = 0.01
defaultBordersLimits = [firstBorderColour, secondBorderColour, thirdBorderColour]
firstBorderColour = shadePixelEpsilon * shadePixelEpsilon
secondBorderColour = shadePixelEpsilon
thirdBorderColour = 2 * shadePixelEpsilon
-----
shadeGrid f step colourMap borderLimits =
let grid =
[
[
shadePixel (x,y) f colourMap borderLimits | x <- [widthFrom, widthFrom + step .. widthTo]
]
| y <- [heightFrom, heightFrom + step .. heightTo]
]
in grid
shadePixel (xPixel, yPixel) f colourMap borderLimits =
shadePixelHelper distanceFromPixelAndFunction colourMap borderLimits
where
functionResultFromX = f xPixel
distanceFromPixelAndFunction = (yPixel - functionResultFromX) * (yPixel - functionResultFromX)
shadePixelHelper _ colourMap [] = last colourMap
shadePixelHelper distanceFromPixelAndFunction
(currentColourMap: restOfColoursMap) (currentBorderLimit : restOfBordersLimit)
| distanceFromPixelAndFunction < currentBorderLimit = currentColourMap
| otherwise = shadePixelHelper distanceFromPixelAndFunction restOfColoursMap restOfBordersLimit
render canvas =
let newLineCanvas = [concat [[p,p] | p <- row] ++ "\n" | row <- canvas]
in concat newLineCanvas
simpleFunc t x = sin (x / 4 + t / 4) * 0.5 * cos (0.5 * x + t / 3) + sin(t/5)
printRenderer t =
let
canvas = render $ shadeGrid (simpleFunc t) stepBetweenPoints defaultColourMap defaultBordersLimits
in canvas `deepseq` putStrLn canvas
clear = system "cls"
loop t = do
clear
printRenderer t
threadDelay 5
loop $ t + 1
main = loop 0
|
@dimitroffangel Вместо да ползваш |
мерси за забележката |
Може да пробваш кода с който е генерирано горното гифче. |
Кода, с който е генерирано гифчето: getFuncValues :: (Enum a, Fractional a) => (a -> b) -> (a, a) -> a -> [(a, b)]
getFuncValues f (xMin, xMax) steps =
map (\x -> (x, f x)) [xMin, xMin + dx .. xMax]
where
dx = (xMax - xMin) / steps
getGrid :: (Enum b, Fractional b) => (b, b) -> (b, b) -> b -> [[(b, b)]]
getGrid (xMin, xMax) (yMin, yMax) resolutionX =
[[(x, y) | x <- [xMin, xMin + dx .. xMax]] | y <- [yMin, yMin + dx .. yMax]]
where
dx = (xMax - xMin) / resolutionX
getCenteredGrid :: (Enum a, Fractional a) => a -> a -> a -> [[(a, a)]]
getCenteredGrid w h = getGrid (- w / 2, w / 2) (- h / 2, h / 2)
mapGrid :: (a -> b) -> [[a]] -> [[b]]
mapGrid f = map (map f)
distance :: Floating a => (a, a) -> (a, a) -> a
distance (x1, y1) (x2, y2) = sqrt (dx ^ 2 + dy ^ 2)
where
dx = x1 - x2
dy = y1 - y2
closeToFuncValue :: Floating t => (t -> t) -> (t, t) -> t
closeToFuncValue f (x, y) = distance (x, y) (x, f x)
showRealGrid :: RealFrac a => [[a]] -> [Char] -> [Char]
showRealGrid grid cmap = stringGrid
where
-- h = length grid
w = length (head grid)
shadePixel p =
let cml = fromIntegral $ length cmap
s = floor (p * (cml - 0.0001))
in cmap !! s
normalizedGrid =
let max = maximum $ map maximum grid
min = minimum $ map minimum grid
in [[(p - min) / (max - min) | p <- row] | row <- grid]
stringRow row = concatMap (replicate 2 . shadePixel) row ++ "\n"
stringGrid = concatMap stringRow normalizedGrid
ditheredCmap :: [Char]
ditheredCmap = reverse " ░▒▓█"
shader :: (Enum a, Floating a, RealFrac a) => a -> a -> a -> [Char]
shader w h t = renderedGrid
where
scale = sin (t / 10) * 0.5 + 2
lineWidth = sin t * 0.5 + 3
f x = x * sin (x / 4 + t / 4) * 0.5 * cos (0.5 * x + t / 3) + sin (t / 5)
scaledFunc x = - f (x / scale) * scale
uv = getCenteredGrid w h w
distField = mapGrid (min lineWidth . closeToFuncValue scaledFunc) uv
renderedGrid = showRealGrid distField ditheredCmap
loop :: (RealFrac p2, RealFrac p1, RealFrac t) => (p2 -> p1 -> t -> [Char]) -> IO b
loop render = animationFrame 0
where
w = 80
h = 40
animationFrame t = do
putStr $ clear (round w + 1) (round h + 1)
putStr $ "T:" ++ show (round t) ++ render w h t
animationFrame (t + 1)
clear w h = "\ESC[" ++ show h ++ "A\ESC[" ++ show w ++ "D"
main :: IO ()
main = loop shader |
Напишете Console Function Plotter на хаскел
(не е задължително вашето решение да изглежда точно както примера).
Може да използвате следната ф-я за да анимирате function plotter-a си.
трябва само да подадете ф-я
render
, която да приема размера на екрана иt
- време и трябва да върне стринг репрезентиращ изрендения фрейм.Следният код е използван за плотването на ф-ята от гифчето:
Използвайте набора от символи от първата бонус задачка -
░▒▓█
Ресурси
Публикувайте решенията като коментари в това
issue
директно или като линкове към репо/gist.Заградете кода на решението си по следния начин за да се highlight-не правилно кода ако публикувате тук:
Всеки валидно решение ще получи бонус точка 🌟.
Дерзайте!
The text was updated successfully, but these errors were encountered: