Рисуем нарядные новогодние ёлочки символами ASCII (и не только)

ёлочка

Новый год уже на пороге, а праздничное настроение куда-то затерялось? Предлагаем подборку из простых и нарядных решений для создания главных зимних красавиц из символов ASCII.

Черно-белая, но ослепительная

Казалось бы, что такого можно слепить из 56 коротеньких строчек кода на JS? Создаем пустой HTML, приправляем его самыми простыми стилями:

body {
margin: 50px auto;
#tree {
font-family: monospace;
text-align: center;
  }
}

И добавляем капельку волшебства:

var decorate = (n, offset, lights) => {
  var decoration, pos = [];

	decoration = Array(n + 1).join("~");

	for(var j = 0; j < lights; j++) pos.push(offset + j);

	var arr = decoration.split("");
	for(var j = 0; j < n; j++){
		if(pos.indexOf(j) > -1) arr[j] = "o";
	}
	decoration = arr.join("");
	
  return decoration;
}

var indent = (n) => {
	var indents = "";
  for(var i = 0; i < n; i++) indents += " ";
  return indents;
}

var tree = (height, lights) => {
  var branch = "", decoPos = 1, offset = -lights;
	
	branch += indent(height - 1);
	branch += "@";
	branch += indent(height - 1);
	branch += "
";
	
  for(var i = 1; i <= height; i++){
    branch += indent(height - i, " ");
    branch += decorate(decoPos, offset, lights);
    branch += indent(height - i, " ");
    
    decoPos += 2;
		offset += 3;
		offset %= decoPos;
    branch += "
";
  }
	
	branch += indent(height - 1);
	branch += "#";
	branch += indent(height - 1);
  
  return branch;
}


var i = 1;
document.getElementById("tree").innerHTML = tree(20, i++);
setInterval(() => {
	document.getElementById("tree").innerHTML = tree(20, i);
	i %= 4;
	i++;
}, 2500);

Вуа-ля:

Праздник в консоли

Очередной шедевр символьной мысли — призер польского конкурса художеств в ASCII. Ёлочка на C++ открывает широкий простор для воображения. Простая праздничная программка позволяет:

  • Украшать дерево звездами, цепочками, шарами, конфетами и огнями;
  • Класть под ёлку подарки с именами любимых;
  • Экспортировать созданную открытку в текстовый файл.

Украшенная елка из символов ASCII

Запустить кроссплатформенную красавицу можно на Windows и Linux. Исходники приложения, а также уже собранная программа доступны на GitHub.

Go праздновать!

Программисты на Go предлагают свой вариант решения проблемы отсутствия новогоднего настроения. Это масштабируемая ёлка, которая украшается по желанию пользователя.

Устанавливаем программу:

$ go get github.com/moul/sapin/cmd/sapin

Выбираем рюшечки:

$ sapin --presents --size=5 --star --garlands=4 --color

Наслаждаемся!

Цветная ёлка из символов ASCII с гирляндами и шарамиПрограмма также позволяет создать деревце из смайликов emoji:

$ sapin --size=3 --balls=4 --star --emoji

Ёлочка с шарами из emojiА ещё её можно запустить в Docker:

$ docker run moul/sapin
docker run moul/sapin --size=4 --garlands=2 --star --color --presents
              #
             ***
            *****
           *****~~
            **~~~
           *~~~***
          ~~~******
         ~~*********
        *************
         ***********
        *************
       ***************
      *@***************
     ***@************@**
    *@****************@**
      @****************
     *******************
    *****@***************
   ***********************
  ********@****************
 *****************@*********
*****************************
            |||||
            |||||   _8_8_
            |||||  |  |  |_8_
            |||||  |__|__|___|

Искрящийся JS

Простое и элегантное решение, однозначно создающее атмосферу праздника.

Устанавливаем программу:

$ npm install --save xmas-tree

Две строчки, чтобы зажечь огни:

const xmasTree = require('xmas-tree');
console.log(xmasTree());

Ослепительно!

Мерцающая ёлка из ASCII

Ещё нарядное деревце можно запустить из консоли и немного поиграть с ее внешним видом:

$ npm install --global xmas-tree
$ xmas-tree --help

  Usage
    $ xmas-tree

  Options
    --size number
    --color
    --loop

  Examples
    $ xmas-tree
    $ xmas-tree --size 30
    $ xmas-tree --color
    $ xmas-tree --color --loop
    $ xmas-tree --version

Прекрасная Mathematica

Можно ли украсить дом к новому году с помощью математических функций? Программисты на Wolfram Language в очередной раз показали, какие чудеса можно совершать с помощью точной науки.

Немного непонятных формул:

PD = .5;
s[t_, f_] := t^.6 - f
dt[cl_, ps_, sg_, hf_, dp_, f_, flag_] :=
    Module[{sv, basePt},
           {PointSize[ps],
            sv = s[t, f];
            Hue[cl (1 + Sin[.02 t])/2, 1, .3 + sg .3 Sin[hf sv]],
            basePt = {-sg s[t, f] Sin[sv], -sg s[t, f] Cos[sv], dp + sv};
            Point[basePt],
           If[flag,
              {Hue[cl (1 + Sin[.1 t])/2, 1, .6 + sg .4 Sin[hf sv]], PointSize[RandomReal[.01]],
               Point[basePt + 1/2 RotationTransform[20 sv, {-Cos[sv], Sin[sv], 0}][{Sin[sv], Cos[sv], 0}]]},
              {}]
          }]

frames = ParallelTable[
                       Graphics3D[Table[{
                                         dt[1, .01, -1, 1, 0, f, True], dt[.45, .01, 1, 1, 0, f, True],
                                         dt[1, .005, -1, 4, .2, f, False], dt[.45, .005, 1, 4, .2, f, False]},
                                        {t, 0, 200, PD}],
                                  ViewPoint -> Left, BoxRatios -> {1, 1, 1.3}, 
                                  ViewVertical -> {0, 0, -1},
                                  ViewCenter -> {{0.5, 0.5, 0.5}, {0.5, 0.55}}, Boxed -> False,
                                  PlotRange -> {{-20, 20}, {-20, 20}, {0, 20}}, Background -> Black],
                       {f, 0, 1, .01}];

Export["tree.gif", frames]

И можно наслаждаться игрой света.

Искрящаяся вращающаяся елка на языке Wolfram

Java-дерево

Программисты на языке Java нашли свой оригинальный подход к рисованию новогодней ёлки из простых фигур.

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;
import javax.imageio.ImageIO;

public class ChristmasTree {
    static class Point{
        Point(int a,int b){x=a;y=b;}
        int x,y;
        double distance(Point o){
            int dx=x-o.x;
            int dy=y-o.y;
            return Math.sqrt(dx*dx+dy*dy);
        }
    }
    static int siz;
    static BufferedImage b;
    static Random r=new Random();
    public static void main(String[]args) throws IOException{

        if(args.length==0){
            siz=(new Scanner(System.in)).nextInt();
        }else{
            siz=Integer.parseInt(args[0]);
        }
        b=new BufferedImage(20*siz,30*siz,BufferedImage.TYPE_INT_RGB);
        Graphics2D g=(Graphics2D)b.getGraphics();
        g.setColor(new Color(140,70,20));
        int h=b.getHeight();h*=0.4;
        for(int i=(int)(0.4*b.getWidth());i<(int)(0.6*b.getWidth());i++){
            if(r.nextDouble()<0.3){
                g.drawLine(i,b.getHeight(),i+r.nextInt(2)-1,h);
            }
}
for(int i=h;i<b.getHeight();i++){
            if(r.nextDouble()<0.3){
                g.drawLine((int)(0.4*b.getWidth()),i,(int)(0.6*b.getWidth()),i);
            }
        }
        for(int i=0;i<siz;i++){
            g.setColor(new Color(r.nextInt(4),150+r.nextInt(15),20+r.nextInt(7)));
            g.drawLine(b.getWidth()/2-(int)(b.getWidth()*0.42*i/siz),(int)(b.getHeight()*0.9)+r.nextInt(5)-2,b.getWidth()/2+(int)(b.getWidth()*0.42*i/siz),(int)(b.getHeight()*0.9)+r.nextInt(5)-2);
            g.setColor(new Color(r.nextInt(4),150+r.nextInt(15),20+r.nextInt(7)));
            g.drawLine(b.getWidth()/2-(int)(b.getWidth()*0.42*i/siz),(int)(b.getHeight()*0.9),b.getWidth()/2,(int)(b.getHeight()*(0.1+(.06*i)/siz)));
            g.setColor(new Color(r.nextInt(4),150+r.nextInt(15),20+r.nextInt(7)));
            g.drawLine(b.getWidth()/2+(int)(b.getWidth()*0.42*i/siz),(int)(b.getHeight()*0.9),b.getWidth()/2,(int)(b.getHeight()*(0.1+(.06*i)/siz)));
        }
        g.setColor(new Color(150,120,40));
        g.fillOval((b.getWidth()-siz-2)/2,b.getHeight()/10,siz+2,siz+2);
        g.setColor(new Color(250,240,80));
        g.fillOval((b.getWidth()-siz)/2,b.getHeight()/10,siz,siz);
        Listc=Arrays.asList(new Color(0,255,0),new Color(255,0,0),new Color(130,0,100),new Color(0,0,200),new Color(110,0,200),new Color(200,205,210),new Color(0,240,255),new Color(255,100,0));
        Listpts=new ArrayList<>();
        pts.add(new Point((b.getWidth()-siz)/2,b.getHeight()/10));
        loop:for(int i=0;i<8+siz/4;i++){
            int y=r.nextInt((8*b.getHeight())/11);
            int x=1+(int)(b.getWidth()*0.35*y/((8*b.getHeight())/11));
            x=r.nextInt(2*x)-x+b.getWidth()/2;
            y+=b.getHeight()/8;
            g.setColor(c.get(r.nextInt(c.size())));
            x-=siz/2;
            Point p=new Point(x,y);
            for(Point q:pts){
                if(q.distance(p)<1+2*siz)continue loop;
            }
            pts.add(p);
            g.fillOval(x,y,siz,siz);
        }
        ImageIO.write(b,"png",new File("tree.png"));
    }

Елка на Java

Черепашьи радости

Тем, кто давно хотел попробовать себя в визуальном программировании, посвящается. Прекрасное новогоднее деревце, основанное на спирали Эйлера. Поиграть с дизайном в интерактивном режиме можно здесь.

Змеиные фракталы

В праздничное время есть что предложить и языку Python. Немного фантазии, и фрактальный карнавал уже украшает кодерскую комнату яркими красками.

n = input()*1.

from turtle import *
speed("fastest")
left(90)
forward(3*n)
color("orange", "yellow")
begin_fill()
left(126)
for i in range(5):
    forward(n/5)
    right(144)
    forward(n/5)
    left(72)
end_fill()
right(126)

color("dark green")
backward(n*4.8)
def tree(d, s):
    if d <= 0: return
    forward(s)
    tree(d-1, s*.8)
    right(120)
    tree(d-3, s*.5)
    right(120)
    tree(d-3, s*.5)
    right(120)
    backward(s)
tree(15, n)
backward(n/2)

import time
time.sleep(60)

Елка из фракталов на Python

Ещё больше интересных идей можно найти на Code Golf.

Новогодние каникулы — отличный повод попробовать себя в чём-то новом: например, в «рисовании».

Весёлых праздников!

Светлана Хачатурян