কেবল একটি বদ্ধ বাঁকা দিয়ে একটি চিত্র পুনরায় আঁকুন


74

Vi.sualize.us দ্বারা অনুপ্রাণিত

লক্ষ্য

ইনপুটটি গ্রেস্কেল চিত্র এবং আউটপুট একটি কালো এবং সাদা চিত্র। আউটপুট চিত্রটিতে কেবল একটি বদ্ধ বাঁকা (লুপ) থাকে যা নিজের সাথে ছেদ করতে বা নিজেকে স্পর্শ করার অনুমতি দেয় না। লাইনের প্রস্থ পুরো চিত্র জুড়ে স্থির থাকবে। এখানে চ্যালেঞ্জটি এটি করার জন্য একটি অ্যালগরিদম সন্ধান করছে। আউটপুটটিতে কেবল ইনপুট চিত্রটি উপস্থাপন করতে হবে তবে কোনও শৈল্পিক স্বাধীনতার সাথে। রেজোলিউশনটি তেমন গুরুত্বপূর্ণ নয় তবে দিক অনুপাত একইরকম থাকা উচিত।

উদাহরণ

এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন

আরও পরীক্ষা চিত্র

লচ নেস গগনচুম্বী আইনস্টাইন পরীক্ষক


2
আপনি আপেক্ষিক রেজোলিউশনে কিছুটা বিধিনিষেধ আরোপ করতে চাইতে পারেন । অন্যথায় কেউ কেবল রেজোলিউশনটিকে যথেষ্ট পরিমাণে বাড়িয়ে তুলতে পারে (32 বা কোনও কিছুর একটি ফ্যাক্টর বলুন) এবং তারপরে প্রতিটি পিক্সেলকে যথাযথ গড় তীব্রতার 32x32 ব্লক দিয়ে প্রতিস্থাপন করতে পারেন। ব্লকগুলিকে সমস্ত সংযুক্ত করার জন্য এটি যথেষ্ট সহজ হওয়া উচিত এবং সেগুলি এমনভাবে সাজানো যাতে সবকিছু একক লুপের সাথে সংযোগ স্থাপন করে।
মার্টিন ইন্ডার

1
যদি লাইনটি নিজেকে স্পর্শ করতে না পারে তবে কোনও অন্ধকার অঞ্চল নেই,
গা shade় শেডটি

1
@ মার্টিন The width of the line shall be constant throughout the whole image.তবে এখনও দরকারী ইঙ্গিত
edc65

2
@ এডসি 65 হ্যাঁ ধ্রুবক, তবে আপনি এখনও এটি একটি পিক্সেলের চেয়েও প্রশস্ত করতে পারবেন (ক্রমাগত) আপনি লাইনটির দুটি অংশ এক পিক্সেল দ্বারা পৃথক করতে পারেন এবং তারপরে অঞ্চলটি 50% গড় তীব্রতার চেয়ে গাer় হবে।
মার্টিন ইন্ডার

2
@ গিথুব্যাগগোসাইট ক্রমশঃ ছবিটি কালো এবং সাদা বর্ণের হওয়া উচিত তবে এতে অ্যান্টি-এলিয়জিং প্রভাব রয়েছে কিনা তা বিবেচ্য নয়। এবং আপনার ত্রিভুজভাবে স্পর্শ পিক্সেলের এই পরিস্থিতি এড়াতে চেষ্টা করা উচিত, তবে আবার, যদি চিত্রটিতে এটি কয়েকবার ঘটে তবে এটি ঠিক থাকবে, যতক্ষণ আপনি এটি পদ্ধতিগতভাবে ব্যবহার না করেন do ইনপুট দেওয়ার জন্য আপনাকে ধন্যবাদ। @ এডসি 65: হ্যাঁ আমি এটি সম্পর্কে সচেতন, লক্ষ্যটি হ'ল দর্শক এখনও চিত্রের একটি আলাদা লাইন সনাক্ত করতে পারে (জুম ইন করার সময়)।
flawr

উত্তর:


34

জাভা: ডট ম্যাট্রিক্স শৈলী

যেহেতু কেউ এখনও প্রশ্নের উত্তর দেয়নি আমি এটিকে একটি শট দেব। প্রথমে আমি হিলবার্ট কার্ভগুলি দিয়ে একটি ক্যানভাস পূরণ করতে চেয়েছিলাম, তবে শেষ পর্যন্ত আমি একটি সহজ পদ্ধতির পক্ষে বেছে নিয়েছি:

ডট ম্যাট্রিক্স স্টাইল মোনা লিসা

কোডটি এখানে:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class LineArt extends JPanel {
    private BufferedImage ref;
    //Images are stored in integers:
    int[] images = new int[] {31, 475, 14683, 469339};
    int[] brightness = new int[] {200,170,120,0};

    public static void main(String[] args) throws Exception {
        new LineArt(args[0]);
    }

    public LineArt(String filename) throws Exception {
        ref = ImageIO.read(new File(filename));
        JFrame frame = new JFrame();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(ref.getWidth()*5, ref.getHeight()*5);
        this.setPreferredSize(new Dimension((ref.getWidth()*5)+20, (ref.getHeight()*5)+20));
        frame.add(new JScrollPane(this));
    }

    @Override
    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, getWidth(), getHeight());
        g2d.translate(10, 10);
        g2d.setColor(Color.BLACK);
        g2d.drawLine(0, 0, 4, 0);
        g2d.drawLine(0, 0, 0, ref.getHeight()*5);

        for(int y = 0; y<ref.getHeight();y++) {
            for(int x = 1; x<ref.getWidth()-1;x++) {
                int light = new Color(ref.getRGB(x, y)).getRed();
                int offset = 0;
                while(brightness[offset]>light) offset++;
                for(int i = 0; i<25;i++) {
                    if((images[offset]&1<<i)>0) {
                        g2d.drawRect((x*5)+i%5, (y*5)+(i/5), 0,0);
                    }
                }
            }
            g2d.drawLine(2, (y*5), 4, (y*5));
            g2d.drawLine((ref.getWidth()*5)-5, (y*5), (ref.getWidth()*5)-1, (y*5));
            if(y%2==0) {
                g2d.drawLine((ref.getWidth()*5)-1, (y*5), (ref.getWidth()*5)-1, (y*5)+4);
            } else {
                g2d.drawLine(2, (y*5), 2, (y*5)+4);
            }
        }
        if(ref.getHeight()%2==0) {
            g2d.drawLine(0, ref.getHeight()*5, 2, ref.getHeight()*5);
        } else {
            g2d.drawLine(0, ref.getHeight()*5, (ref.getWidth()*5)-1, ref.getHeight()*5);
        }
    }
}

আপডেট : এখন এটি একটি একক লাইন নয়, একটি চক্র তৈরি করে


2
খুব সুন্দর এবং সহজ সমাধান, আমি এটিকে সমাধান করার উপায়টি কল্পনা করিনি তবে এটি দুর্দান্ত দেখাচ্ছে!
flawr

@ ডেনডেনডো একটি বক্ররেখা সংক্ষিপ্ত প্রবাহ অ্যানিমেশন প্লট করার পরামর্শ দিয়েছিল। আপনি যদি সঠিক ক্রমে ব্যবহার করেন এমন সমস্ত কনারার পয়েন্টগুলির স্থানাঙ্কের সাথে যদি আপনি একটি পাঠ্য ফাইল (সিএসভি বা আপনি যা চান) সরবরাহ করতে পারেন তবে দুর্দান্ত হবে great অ্যানিমেশন গণনা করার জন্য আমি একটি ম্যাটলব স্ক্রিপ্ট তৈরি করেছি - তবে অবশ্যই আপনি নিজে এটি
করতেও

35

পাইথন: হিলবার্ট কার্ভ ( 373 361)

আমি ইমেজের তীব্রতার উপর নির্ভর করে ভেরিয়েবল গ্রানুলারিটি সহ একটি হিলবার্ট কার্ভ আঁকার সিদ্ধান্ত নিয়েছি:

import pylab as pl
from scipy.misc import imresize, imfilter
import turtle

# load image
img = pl.flipud(pl.imread("face.png"))

# setup turtle
levels = 8
size = 2**levels
turtle.setup(img.shape[1] * 4.2, img.shape[0] * 4.2)
turtle.setworldcoordinates(0, 0, size, -size)
turtle.tracer(1000, 0)

# resize and blur image
img = imfilter(imresize(img, (size, size)), 'blur')

# define recursive hilbert curve
def hilbert(level, angle = 90):
    if level == 0:
        return
    if level == 1 and img[-turtle.pos()[1], turtle.pos()[0]] > 128:
        turtle.forward(2**level - 1)
    else:
        turtle.right(angle)
        hilbert(level - 1, -angle)
        turtle.forward(1)
        turtle.left(angle)
        hilbert(level - 1, angle)
        turtle.forward(1)
        hilbert(level - 1, angle)
        turtle.left(angle)
        turtle.forward(1)
        hilbert(level - 1, -angle)
        turtle.right(angle)

# draw hilbert curve
hilbert(levels)
turtle.update()

আসলে আমি বিভিন্ন স্তরের বিশদ নিয়ে সিদ্ধান্ত নেওয়ার পরিকল্পনা করেছি, যেমন "এই স্পটটি এত উজ্জ্বল, আমি পুনরাবৃত্তিটি থামাব এবং পরবর্তী ব্লকে চলে যাব!"! তবে স্থানীয়ভাবে চিত্রের তীব্রতার মূল্যায়ন করা বড় চলাচলের দিকে পরিচালিত করে খুব অসম্পূর্ণ এবং দেখতে দেখতে কুৎসিত। সুতরাং আমি কেবলমাত্র স্তর 1 এড়িয়ে যাবেন বা অন্য একটি হিলবার্ট লুপ আঁকবেন কিনা তা ঠিক করেই শেষ করেছি।

এখানে প্রথম পরীক্ষার চিত্রের ফলাফল:

ফলাফল

@ Githubphagocyte ধন্যবাদ রেন্ডারিং বেশ দ্রুত (ব্যবহার করে turtle.tracer)। সুতরাং ফলাফলের জন্য আমাকে সারা রাত অপেক্ষা করতে হবে না এবং আমার ভাল বিছানায় যেতে পারি। :)


কিছু কোড গল্ফ

@ ফ্লোয়ার: "শর্ট প্রোগ্রাম"? আপনি গল্ফ সংস্করণ দেখেন নি! ;)

তাই কেবল মজাদার জন্য:

from pylab import*;from scipy.misc import*;from turtle import*
i=imread("f.p")[::-1];s=256;h=i.shape;i=imfilter(imresize(i,(s,s)),'blur')
setup(h[1]*4.2,h[0]*4.2);setworldcoordinates(0,0,s,-s);f=forward;r=right
def h(l,a=90):
 x,y=pos()
 if l==1and i[-y,x]>128:f(2**l-1)
 else:
  if l:l-=1;r(a);h(l,-a);f(1);r(-a);h(l,a);f(1);h(l,a);r(-a);f(1);h(l,-a);r(a)
h(8)

( 373 361 অক্ষর। কিন্তু এটা সব সময় প্রবেশ করুন যেহেতু আমি অপসারণ নিতে হবে turte.tracer(...)কমান্ড!)


Flawr দ্বারা অ্যানিমেশন

ত্রুটি: @ অ্যালগরিদম @DenDenDo আমাকে যা বলেছিল তাতে কিছুটা সংশোধন করা হয়েছে: আমাকে প্রতিটি পুনরাবৃত্তির কিছু পয়েন্ট মুছে ফেলতে হয়েছিল কারণ এই অভিব্যক্তিটি খুব দ্রুত হ্রাস পাবে। এজন্য কার্ভটি নিজেকে ছেদ করবে।

এখানে চিত্র বর্ণনা লিখুন


1
সুন্দরভাবে সম্পন্ন! আপনি যদি দ্রুত দৌড়াতে চান তবে screen.tracer(0)পরিবর্তে চেষ্টা করুন turtle.speed(0)। শুরুতে আপনার পর্দা ইনস্ট্যান্ট করার দরকার হতে পারে তবে এটি যদি পর্দার একমাত্র উদাহরণ হয় তবে আপনার সমস্ত কচ্ছপ স্বয়ংক্রিয়ভাবে এটিকে বরাদ্দ করা হবে। তারপরে ঠিক screen.update()ফলাফলগুলি প্রদর্শন করতে হবে। আমি প্রথম যখন এটি আবিষ্কার করেছি তখন গতির
তফাতটিতে

আমি সত্যিই অবাক হয়েছি যে আপনি এটি একটি সংক্ষিপ্ত প্রোগ্রামে এটি করতে সক্ষম হয়েছিলেন! তবে যাইহোক, অভিনন্দন! fractals ftw =)
flawr

@ ডেনডেনডো একটি বক্ররেখা সংক্ষিপ্ত প্রবাহ অ্যানিমেশন প্লট করার পরামর্শ দিয়েছিল। আপনি যদি সঠিক ক্রমে ব্যবহার করেন এমন সমস্ত কনারার পয়েন্টগুলির স্থানাঙ্কের সাথে যদি আপনি একটি পাঠ্য ফাইল (সিএসভি বা আপনি যা চান) সরবরাহ করতে পারেন তবে দুর্দান্ত হবে great অ্যানিমেশন গণনা করার জন্য আমি একটি ম্যাটলব স্ক্রিপ্ট তৈরি করেছি - তবে অবশ্যই আপনি নিজে এটি
করতেও

@ ফ্লোয়ার: এখানে আমরা যাই।
ফালকো

সুতরাং কোডটি এখানে: পেস্টবিন.
com

32

পাইথন ৩.৪ - ভ্রমণকারী বিক্রয় সমস্যা

প্রোগ্রামটি মূল থেকে একটি বিশিষ্ট চিত্র তৈরি করে:

এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন

প্রতিটি কালো পিক্সেলের জন্য পিক্সেল কেন্দ্রের নিকটে এলোমেলোভাবে একটি বিন্দু উত্পন্ন হয় এবং এই পয়েন্টগুলি ভ্রমণ বিক্রয় সমস্যা হিসাবে বিবেচিত হয় । প্রোগ্রামটি নিয়মিত বিরতিতে একটি এসভিজি চিত্রযুক্ত একটি এইচটিএমএল ফাইল সংরক্ষণ করে কারণ এটি পথের দৈর্ঘ্য হ্রাস করার চেষ্টা করে। পথটি নিজেকে ছেদ করা শুরু করে এবং কয়েক ঘন্টা ধরে ধীরে ধীরে কম হয়ে যায়। শেষ পর্যন্ত পথটি আর নিজেকে ছেদ করা যায় না:

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

'''
Traveling Salesman image approximation.
'''

import os.path

from PIL import Image   # This uses Pillow, the PIL fork for Python 3.4
                        # https://pypi.python.org/pypi/Pillow

from random import random, sample, randrange, shuffle
from time import perf_counter


def make_line_picture(image_filename):
    '''Save SVG image of closed curve approximating input image.'''
    input_image_path = os.path.abspath(image_filename)
    image = Image.open(input_image_path)
    width, height = image.size
    scale = 1024 / width
    head, tail = os.path.split(input_image_path)
    output_tail = 'TSP_' + os.path.splitext(tail)[0] + '.html'
    output_filename = os.path.join(head, output_tail)
    points = generate_points(image)
    population = len(points)
    save_dither(points, image)
    grid_cells = [set() for i in range(width * height)]
    line_cells = [set() for i in range(population)]
    print('Initialising acceleration grid')
    for i in range(population):
        recalculate_cells(i, width, points, grid_cells, line_cells)
    while True:
        save_svg(output_filename, width, height, points, scale)
        improve_TSP_solution(points, width, grid_cells, line_cells)


def save_dither(points, image):
    '''Save a copy of the dithered image generated for approximation.'''
    image = image.copy()
    pixels = list(image.getdata())
    pixels = [255] * len(pixels)
    width, height = image.size
    for p in points:
        x = int(p[0])
        y = int(p[1])
        pixels[x+y*width] = 0
    image.putdata(pixels)
    image.save('dither_test.png', 'PNG')


def generate_points(image):
    '''Return a list of points approximating the image.

    All points are offset by small random amounts to prevent parallel lines.'''
    width, height = image.size
    image = image.convert('L')
    pixels = image.getdata()
    points = []
    gap = 1
    r = random
    for y in range(2*gap, height - 2*gap, gap):
        for x in range(2*gap, width - 2*gap, gap):
            if (r()+r()+r()+r()+r()+r())/6 < 1 - pixels[x + y*width]/255:
                        points.append((x + r()*0.5 - 0.25,
                                       y + r()*0.5 - 0.25))
    shuffle(points)
    print('Total number of points', len(points))
    print('Total length', current_total_length(points))
    return points


def current_total_length(points):
    '''Return the total length of the current closed curve approximation.'''
    population = len(points)
    return sum(distance(points[i], points[(i+1)%population])
               for i in range(population))


def recalculate_cells(i, width, points, grid_cells, line_cells):
    '''Recalculate the grid acceleration cells for the line from point i.'''
    for j in line_cells[i]:
        try:
            grid_cells[j].remove(i)
        except KeyError:
            print('grid_cells[j]',grid_cells[j])
            print('i',i)
    line_cells[i] = set()
    add_cells_along_line(i, width, points, grid_cells, line_cells)
    for j in line_cells[i]:
        grid_cells[j].add(i)


def add_cells_along_line(i, width, points, grid_cells, line_cells):
    '''Add each grid cell that lies on the line from point i.'''
    population = len(points)
    start_coords = points[i]
    start_x, start_y = start_coords
    end_coords = points[(i+1) % population]
    end_x, end_y = end_coords
    gradient = (end_y - start_y) / (end_x - start_x)
    y_intercept = start_y - gradient * start_x
    total_distance = distance(start_coords, end_coords)
    x_direction = end_x - start_x
    y_direction = end_y - start_y
    x, y = start_x, start_y
    grid_x, grid_y = int(x), int(y)
    grid_index = grid_x + grid_y * width
    line_cells[i].add(grid_index)
    while True:
        if x_direction > 0:
            x_line = int(x + 1)
        else:
            x_line = int(x)
            if x_line == x:
                x_line = x - 1
        if y_direction > 0:
            y_line = int(y + 1)
        else:
            y_line = int(y)
            if y_line == y:
                y_line = y - 1
        x_line_intersection = gradient * x_line + y_intercept
        y_line_intersection = (y_line - y_intercept) / gradient
        x_line_distance = distance(start_coords, (x_line, x_line_intersection))
        y_line_distance = distance(start_coords, (y_line_intersection, y_line))
        if (x_line_distance > total_distance and
            y_line_distance > total_distance):
            break
        if x_line_distance < y_line_distance:
            x = x_line
            y = gradient * x_line + y_intercept
        else:
            y = y_line
            x = (y_line - y_intercept) / gradient
        grid_x = int(x - (x_direction < 0) * (x == int(x)))
        grid_y = int(y - (y_direction < 0) * (y == int(y)))
        grid_index = grid_x + grid_y * width
        line_cells[i].add(grid_index)


def improve_TSP_solution(points, width, grid_cells, line_cells,
                         performance=[0,0,0], total_length=None):
    '''Apply 3 approaches, allocating time to each based on performance.'''
    population = len(points)
    if total_length is None:
        total_length = current_total_length(points)

    print('Swapping pairs of vertices')
    if performance[0] == max(performance):
        time_limit = 300
    else:
        time_limit = 10
    print('    Aiming for {} seconds'.format(time_limit))
    start_time = perf_counter()
    for n in range(1000000):
        swap_two_vertices(points, width, grid_cells, line_cells)
        if perf_counter() - start_time > time_limit:
            break
    time_taken = perf_counter() - start_time
    old_length = total_length
    total_length = current_total_length(points)
    performance[0] = (old_length - total_length) / time_taken
    print('    Time taken', time_taken)
    print('    Total length', total_length)
    print('    Performance', performance[0])

    print('Moving single vertices')
    if performance[1] == max(performance):
        time_limit = 300
    else:
        time_limit = 10
    print('    Aiming for {} seconds'.format(time_limit))
    start_time = perf_counter()
    for n in range(1000000):
        move_a_single_vertex(points, width, grid_cells, line_cells)
        if perf_counter() - start_time > time_limit:
            break
    time_taken = perf_counter() - start_time
    old_length = total_length
    total_length = current_total_length(points)
    performance[1] = (old_length - total_length) / time_taken
    print('    Time taken', time_taken)
    print('    Total length', total_length)
    print('    Performance', performance[1])

    print('Uncrossing lines')
    if performance[2] == max(performance):
        time_limit = 60
    else:
        time_limit = 10
    print('    Aiming for {} seconds'.format(time_limit))
    start_time = perf_counter()
    for n in range(1000000):
        uncross_lines(points, width, grid_cells, line_cells)
        if perf_counter() - start_time > time_limit:
            break
    time_taken = perf_counter() - start_time        
    old_length = total_length
    total_length = current_total_length(points)
    performance[2] = (old_length - total_length) / time_taken
    print('    Time taken', time_taken)
    print('    Total length', total_length)
    print('    Performance', performance[2])


def swap_two_vertices(points, width, grid_cells, line_cells):
    '''Attempt to find a pair of vertices that reduce length when swapped.'''
    population = len(points)
    for n in range(100):
        candidates = sample(range(population), 2)
        befores = [(candidates[i] - 1) % population
                   for i in (0,1)]
        afters = [(candidates[i] + 1) % population for i in (0,1)]
        current_distance = sum((distance(points[befores[i]],
                                         points[candidates[i]]) +
                                distance(points[candidates[i]],
                                         points[afters[i]]))
                               for i in (0,1))
        (points[candidates[0]],
         points[candidates[1]]) = (points[candidates[1]],
                                   points[candidates[0]])
        befores = [(candidates[i] - 1) % population
                   for i in (0,1)]
        afters = [(candidates[i] + 1) % population for i in (0,1)]
        new_distance = sum((distance(points[befores[i]],
                                     points[candidates[i]]) +
                            distance(points[candidates[i]],
                                     points[afters[i]]))
                           for i in (0,1))
        if new_distance > current_distance:
            (points[candidates[0]],
             points[candidates[1]]) = (points[candidates[1]],
                                       points[candidates[0]])
        else:
            modified_points = tuple(set(befores + candidates))
            for k in modified_points:
                recalculate_cells(k, width, points, grid_cells, line_cells)
            return


def move_a_single_vertex(points, width, grid_cells, line_cells):
    '''Attempt to find a vertex that reduces length when moved elsewhere.'''
    for n in range(100):
        population = len(points)
        candidate = randrange(population)
        offset = randrange(2, population - 1)
        new_location = (candidate + offset) % population
        before_candidate = (candidate - 1) % population
        after_candidate = (candidate + 1) % population
        before_new_location = (new_location - 1) % population
        old_distance = (distance(points[before_candidate], points[candidate]) +
                        distance(points[candidate], points[after_candidate]) +
                        distance(points[before_new_location],
                                 points[new_location]))
        new_distance = (distance(points[before_candidate],
                                 points[after_candidate]) +
                        distance(points[before_new_location],
                                 points[candidate]) +
                        distance(points[candidate], points[new_location]))
        if new_distance <= old_distance:
            if new_location < candidate:
                points[:] = (points[:new_location] +
                             points[candidate:candidate + 1] +
                             points[new_location:candidate] +
                             points[candidate + 1:])
                for k in range(candidate - 1, new_location, -1):
                    for m in line_cells[k]:
                        grid_cells[m].remove(k)
                    line_cells[k] = line_cells[k - 1]
                    for m in line_cells[k]:
                        grid_cells[m].add(k)
                for k in ((new_location - 1) % population,
                          new_location, candidate):
                    recalculate_cells(k, width, points, grid_cells, line_cells)
            else:
                points[:] = (points[:candidate] +
                             points[candidate + 1:new_location] +
                             points[candidate:candidate + 1] +
                             points[new_location:])
                for k in range(candidate, new_location - 3):
                    for m in line_cells[k]:
                        grid_cells[m].remove(k)
                    line_cells[k] = line_cells[k + 1]
                    for m in line_cells[k]:
                        grid_cells[m].add(k)
                for k in ((candidate - 1) % population,
                          new_location - 2, new_location - 1):
                    recalculate_cells(k, width, points, grid_cells, line_cells)
            return


def uncross_lines(points, width, grid_cells, line_cells):
    '''Attempt to find lines that are crossed, and reverse path to uncross.'''
    population = len(points)
    for n in range(100):
        i = randrange(population)
        start_1 = points[i]
        end_1 = points[(i + 1) % population]
        if not line_cells[i]:
            recalculate_cells(i, width, points, grid_cells, line_cells)
        for cell in line_cells[i]:
            for j in grid_cells[cell]:
                if i != j and i != (j+1)%population and i != (j-1)%population:
                    start_2 = points[j]
                    end_2 = points[(j + 1) % population]
                    if are_crossed(start_1, end_1, start_2, end_2):
                        if i < j:
                            points[i + 1:j + 1] = reversed(points[i + 1:j + 1])
                            for k in range(i, j + 1):
                                recalculate_cells(k, width, points, grid_cells,
                                                  line_cells)
                        else:
                            points[j + 1:i + 1] = reversed(points[j + 1:i + 1])
                            for k in range(j, i + 1):
                                recalculate_cells(k, width, points, grid_cells,
                                                  line_cells)
                        return


def are_crossed(start_1, end_1, start_2, end_2):
    '''Return True if the two lines intersect.'''
    if end_1[0]-start_1[0] and end_2[0]-start_2[0]:
        gradient_1 = (end_1[1]-start_1[1])/(end_1[0]-start_1[0])
        gradient_2 = (end_2[1]-start_2[1])/(end_2[0]-start_2[0])
        if gradient_1-gradient_2:
            intercept_1 = start_1[1] - gradient_1 * start_1[0]
            intercept_2 = start_2[1] - gradient_2 * start_2[0]        
            x = (intercept_2 - intercept_1) / (gradient_1 - gradient_2)
            if (x-start_1[0]) * (end_1[0]-x) > 0 and (x-start_2[0]) * (end_2[0]-x) > 0:
                return True


def distance(point_1, point_2):
    '''Return the Euclidean distance between the two points.'''
    return sum((point_1[i] - point_2[i]) ** 2 for i in (0, 1)) ** 0.5


def save_svg(filename, width, height, points, scale):
    '''Save a file containing an SVG path of the points.'''
    print('Saving partial solution\n')
    with open(filename, 'w') as file:
        file.write(content(width, height, points, scale))


def content(width, height, points, scale):
    '''Return the full content to be written to the SVG file.'''
    return (header(width, height, scale) +
            specifics(points, scale) +
            footer()
            )


def header(width, height,scale):
    '''Return the text of the SVG header.'''
    return ('<?xml version="1.0"?>\n'
            '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"\n'
            '    "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\n'
            '\n'
            '<svg width="{0}" height="{1}">\n'
            '<title>Traveling Salesman Problem</title>\n'
            '<desc>An approximate solution to the Traveling Salesman Problem</desc>\n'
            ).format(scale*width, scale*height)


def specifics(points, scale):
    '''Return text for the SVG path command.'''
    population = len(points)
    x1, y1 = points[-1]
    x2, y2 = points[0]
    x_mid, y_mid = (x1 + x2) / 2, (y1 + y2) / 2
    text = '<path d="M{},{} L{},{} '.format(x1, y1, x2, y2)
    for i in range(1, population):
        text += 'L{},{} '.format(*points[i])
    text += '" stroke="black" fill="none" stroke-linecap="round" transform="scale({0},{0})" vector-effect="non-scaling-stroke" stroke-width="3"/>'.format(scale)
    return text


def footer():
    '''Return the closing text of the SVG file.'''
    return '\n</svg>\n'


if __name__ == '__main__':
    import sys
    arguments = sys.argv[1:]
    if arguments:
        make_line_picture(arguments[0])
    else:
        print('Required argument: image file')

প্রোগ্রামটি উন্নতির জন্য 3 টি পৃথক পদ্ধতি ব্যবহার করে এবং প্রতি সেকেন্ডের জন্য পারফরম্যান্সকে পরিমাপ করে। প্রতিটি পদ্ধতির জন্য বরাদ্দকৃত সময়টি সেই সময়ে সবচেয়ে ভাল যেভাবে সম্পাদন করা হয় তার বেশিরভাগ সময়কে সামঞ্জস্য করে।

আমি প্রথমে প্রতিটি পদ্ধতির জন্য কী পরিমাণ অনুপাত বরাদ্দ করেছিলাম তা অনুমান করার চেষ্টা করেছি, তবে এটি প্রমাণিত হয় যে কোন পদ্ধতিটি সবচেয়ে কার্যকর তা প্রক্রিয়া চলাকালীন সময়ে যথেষ্ট পরিবর্তিত হয়, তাই এটি স্বয়ংক্রিয়ভাবে সামঞ্জস্য হতে বড় পার্থক্য করে।

তিনটি সহজ পন্থা হ'ল:

  1. এলোমেলোভাবে দুটি পয়েন্ট বাছুন এবং এটি মোট দৈর্ঘ্য না বাড়িয়ে দিলে এগুলিকে অদলবদল করুন।
  2. পয়েন্টগুলির তালিকার সাথে এলোমেলোভাবে একটি পয়েন্ট এবং এলোমেলোভাবে বেছে নিন এবং দৈর্ঘ্য না বাড়লে এটিকে সরান।
  3. এলোমেলোভাবে একটি লাইন বাছুন এবং অন্য কোনও লাইন এটি অতিক্রম করে কিনা তা পরীক্ষা করে দেখুন, পথের যে কোনও অংশ ক্রস হওয়ার কারণ হিসাবে বিপরীত।

3 পদ্ধতির জন্য একটি গ্রিড ব্যবহৃত হয়, প্রদত্ত কক্ষটি অতিক্রম করে এমন সমস্ত রেখার তালিকা করে। ছেদ করার জন্য পৃষ্ঠার প্রতিটি লাইন পরীক্ষা করার পরিবর্তে, কেবল গ্রিড সেল রয়েছে এমন ব্যক্তিদেরই চেক করা হয়।


এই চ্যালেঞ্জটি পোস্ট হওয়ার আগে আমি দেখেছিলাম যে কোনও ব্লগ পোস্ট থেকে ট্র্যাভেল বিক্রয় ব্যবসায়ী সমস্যাটি ব্যবহার করার ধারণাটি পেয়েছি, তবে আমি এই উত্তরটি পোস্ট করার পরে এটি ট্র্যাক করতে পারি না। আমি বিশ্বাস করি যে চ্যালেঞ্জের চিত্রটি কোনও ভ্রমণকারী বিক্রয়িক পদ্ধতির ব্যবহার করেও তৈরি করা হয়েছিল, যার ফলে ধারালো বাঁকগুলি মুছে ফেলার জন্য এক ধরণের পথের মসৃণতা রয়েছে।

আমি এখনও নির্দিষ্ট ব্লগ পোস্টটি খুঁজে পাচ্ছি না তবে আমি এখন মূল কাগজপত্রগুলির রেফারেন্স পেয়েছি যেখানে মোনা লিসা ভ্রমণকারী বিক্রয়কর্মী সমস্যাটি প্রদর্শনের জন্য ব্যবহৃত হয়েছিল

এখানে টিএসপি বাস্তবায়ন হ'ল একটি হাইব্রিড পদ্ধতির যা আমি এই চ্যালেঞ্জটির জন্য মজা করার জন্য পরীক্ষা করেছি। আমি এটি পোস্ট করার সময় লিঙ্কিত কাগজপত্র পড়িনি। আমার পদ্ধতির তুলনা করে যন্ত্রণাদায়কভাবে ধীরে ধীরে। নোট করুন যে আমার চিত্রটি এখানে 10,000 টিরও কম পয়েন্ট ব্যবহার করে এবং কোনও ক্রসিং লাইন না পেয়ে পর্যাপ্ত রূপান্তর করতে বেশ কয়েক ঘন্টা সময় নেয়। কাগজগুলির লিঙ্কে উদাহরণ চিত্রটি 100,000 পয়েন্ট ব্যবহার করে ...

দুর্ভাগ্যক্রমে বেশিরভাগ লিঙ্কগুলি এখন মৃত বলে মনে হচ্ছে, তবে ক্রেগ এস কাপলান এবং রবার্ট বোশ 2005 এর "টিএসপি আর্ট" পত্রিকাটি এখনও কাজ করে এবং বিভিন্ন পদ্ধতির একটি আকর্ষণীয় ওভারভিউ দেয়।


1
বাহ, সত্যিই চমৎকার =) (আপনি যদি চান তবে আমার কোনও বক্ররেখার প্রবাহ অ্যানিমেশনটি করতে চান তবে কেবল বিন্দু স্থানাঙ্কের একটি
আদেশযুক্ত

@ ফ্লোয়ার ধন্যবাদ! নির্দেশিত পয়েন্ট স্থানাঙ্কের তালিকার হিসাবে, এটি মোনা লিসা মুখের জন্য প্রায় 10,000 পয়েন্ট। এটি বড় চিত্রগুলির জন্য আরও 100,000 পয়েন্ট হতে পারে। সে কারণেই আমি এখানে এসভিজি পাঠ্য পোস্ট করি নি ... :)
ট্রাইকোপল্যাক্স

ঠিক আছে আপনি পেস্টবিন.কম বা অনুরূপ কিছু ব্যবহার করতে পারেন, তবে আমি আপনাকে জোর করতে চাই না, এটি আপনার সিদ্ধান্ত (আমি পাইথন = তে ভাল নই)
flawr

@ ফ্লোয়ার আমি চাই না যে প্রোগ্রামটি চালানোর জন্য আপনাকে ঘন্টা এবং ঘন্টা অপেক্ষা করতে হবে। আমি আমার উত্তরে একটি প্রবাহ অ্যানিমেশন যুক্ত করব না তবে আপনি যদি নিজের জন্য পয়েন্টগুলি চান তবে আমাকে জানান এবং আমি সেগুলি পোস্ট করার জন্য কোথাও খুঁজে পেতে পারি ...
ট্রাইকপল্যাক্স

এ জাতীয় জিনিসের জন্য আমার কখনই টিএসপি ধারণা ছিল না! Upvote পান!
সার্জিওল

24

জাভা - দোলনা

প্রোগ্রামটি একটি বদ্ধ পথ আঁকে এবং দোলনা যুক্ত করে যার প্রশস্ততা এবং ফ্রিকোয়েন্সি চিত্রের উজ্জ্বলতার ভিত্তিতে। পাথের "কোণে" দু'টি দোলনা থাকে না তা নিশ্চিত করার জন্য যে পথটি নিজেই ছেদ করে নি।

এখানে চিত্র বর্ণনা লিখুন

package trace;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import snake.Image;

public class Main5 {


    private final static int MULT = 3;
    private final static int ROWS = 80; // must be an even number
    private final static int COLS = 40;

    public static void main(String[] args) throws IOException {
        BufferedImage src = ImageIO.read(Image.class.getClassLoader().getResourceAsStream("input.png"));
        BufferedImage dest = new BufferedImage(src.getWidth()*MULT, src.getHeight()*MULT, BufferedImage.TYPE_INT_RGB);

        int [] white = {255, 255, 255};
        for (int y = 0; y < dest.getHeight(); y++) {
            for (int x = 0; x < dest.getWidth(); x++) {
                dest.getRaster().setPixel(x, y, white);
            }
        }
        for (int j = 0; j < ROWS; j++) {
            if (j%2 == 0) {
                for (int i = j==0 ? 0 : 1; i < COLS-1; i++) {
                    drawLine(dest, src, (i+.5)*dest.getWidth()/COLS, (j+.5)*dest.getHeight()/ROWS, (i+1.5)*dest.getWidth()/COLS, (j+.5)*dest.getHeight()/ROWS,
                            i > 1 && i < COLS-2);
                }

                drawLine(dest, src, (COLS-.5)*dest.getWidth()/COLS, (j+.5)*dest.getHeight()/ROWS, (COLS-.5)*dest.getWidth()/COLS, (j+1.5)*dest.getHeight()/ROWS, false);
            } else {
                for (int i = COLS-2; i >= (j == ROWS - 1 ? 0 : 1); i--) {
                    drawLine(dest, src, (i+.5)*dest.getWidth()/COLS, (j+.5)*dest.getHeight()/ROWS, (i+1.5)*dest.getWidth()/COLS, (j+.5)*dest.getHeight()/ROWS,
                            i > 1 && i < COLS-2);
                }
                if (j < ROWS-1) {
                    drawLine(dest, src, (1.5)*dest.getWidth()/COLS, (j+.5)*dest.getHeight()/ROWS, (1.5)*dest.getWidth()/COLS, (j+1.5)*dest.getHeight()/ROWS, false);
                }
            }
            if (j < ROWS-1) {
                drawLine(dest, src, 0.5*dest.getWidth()/COLS, (j+.5)*dest.getHeight()/ROWS, 0.5*dest.getWidth()/COLS, (j+1.5)*dest.getHeight()/ROWS, false);
            }
        }
        ImageIO.write(dest, "png", new File("output.png"));
    }

    private static void drawLine(BufferedImage dest, BufferedImage src, double x1, double y1, double x2, double y2, boolean oscillate) {
        int [] black = {0, 0, 0};

        int col = smoothPixel((int)((x1*.5 + x2*.5) / MULT), (int)((y1*.5+y2*.5) / MULT), src);
        int fact = (255 - col) / 32;
        if (fact > 5) fact = 5;
        double dx = y1 - y2;
        double dy = - (x1 - x2);
        double dist = 2 * (Math.abs(x1 - x2) + Math.abs(y1 - y2)) * (fact + 1);
        for (int i = 0; i <= dist; i++) {
            double amp = oscillate ? (1 - Math.cos(fact * i*Math.PI*2/dist)) * 12 : 0;
            double x = (x1 * i + x2 * (dist - i)) / dist;
            double y = (y1 * i + y2 * (dist - i)) / dist;
            x += dx * amp / COLS;
            y += dy * amp / ROWS;
            dest.getRaster().setPixel((int)x, (int)y, black);
        }
    }

    public static int smoothPixel(int x, int y, BufferedImage src) {
        int sum = 0, count = 0;
        for (int j = -2; j <= 2; j++) {
            for (int i = -2; i <= 2; i++) {
                if (x + i >= 0 && x + i < src.getWidth()) {
                    if (y + j >= 0 && y + j < src.getHeight()) {
                        sum += src.getRGB(x + i, y + j) & 255;
                        count++;
                    }
                }
            }
        }
        return sum / count;
    }
}

তুলনামূলক অ্যালগরিদমের নীচে যা সর্পিলের উপর ভিত্তি করে। ( আমি জানি পথটি বন্ধ হয় না এবং এটি অবশ্যই ছেদ করে , আমি কেবল এটি শিল্পের জন্য পোস্ট করি :-)

এখানে চিত্র বর্ণনা লিখুন


আমি বিশেষত সর্পিলের ভিজ্যুয়াল এফেক্টটি পছন্দ করি!
উইল

আমিও, ভাগ করে নেওয়ার জন্য ধন্যবাদ! (আপনি যদি চান তবে আপনিও একটি নির্দেশিত পথের পয়েন্টের তালিকা তৈরি করতে পারেন এবং আমি এটির সাথে একটি অ্যানিমেশনও করতে পারি কিনা তা আমি দেখতে পাচ্ছি =)
flawr

@ গিথুব আপনার গঠনমূলক মন্তব্যের জন্য ধন্যবাদ।
Arnaud

1
আমার কাছ থেকে +1 - এটি এখন নিয়মগুলি পুরোপুরি ফিট করে এবং পরিবর্তিত ফ্রিকোয়েন্সি যে মসৃণ স্থানান্তর দেয় তা আমি পছন্দ করি।
ট্রাইকোপলাক্স

21

জাভা - পুনরাবৃত্তির পথ

আমি 2x3 বন্ধ পথ থেকে শুরু করি। আমি পাথের প্রতিটি কক্ষ স্ক্যান করে এটিকে একটি নতুন 3x3 উপ-পথে ভাগ করেছি divide আমি প্রতিবার চেষ্টা করি 3x3 সাব-পাথটি মূল ছবিটি "দেখতে" পছন্দ করুন। আমি উপরের প্রক্রিয়াটি 4 বার পুনরাবৃত্তি করি।

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

কোডটি এখানে:

package divide;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.imageio.ImageIO;

import snake.Image;

public class Divide {

    private final static int MULT = 3;
    private final static int ITERATIONS = 4;

    public static void main(String[] args) throws IOException {
        BufferedImage src = ImageIO.read(Image.class.getClassLoader().getResourceAsStream("input.png"));
        BufferedImage dest = new BufferedImage(src.getWidth() * MULT, src.getHeight() * MULT, BufferedImage.TYPE_INT_RGB);
        for (int y = 0; y < src.getHeight() * MULT; y++) {
            for (int x = 0; x < src.getWidth() * MULT; x++) {
                dest.getRaster().setPixel(x, y, new int [] {255, 255, 255});
            }
        }
        List<String> tab = new ArrayList<String>();
        tab.add("rg");
        tab.add("||"); 
        tab.add("LJ");

        for (int k = 1; k <= ITERATIONS; k++) {
            boolean choose = k>=ITERATIONS-1;
            // multiply size by 3
            tab = iterate(src, tab, choose);
            // fill in the white space - if needed
            expand(src, tab, " r", " L", "r-", "L-", choose);
            expand(src, tab, "g ", "J ", "-g", "-J", choose);
            expand(src, tab, "LJ", "  ", "||", "LJ", choose);
            expand(src, tab, "  ", "rg", "rg", "||", choose);
            expand(src, tab, "L-J", "   ", "| |", "L-J", choose);
            expand(src, tab, "   ", "r-g", "r-g", "| |", choose);
            expand(src, tab, "| |", "| |", "Lg|", "rJ|", choose);
            expand(src, tab, "--", "  ", "gr", "LJ", choose);
            expand(src, tab, "  ", "--", "rg", "JL", choose);
            expand(src, tab, "| ", "| ", "Lg", "rJ", choose);
            expand(src, tab, " |", " |", "rJ", "Lg", choose);

            for (String s : tab) {
                System.out.println(s);
            }
            System.out.println();
        }

        for (int j = 0; j < tab.size(); j++) {
            String line = tab.get(j);
            for (int i = 0; i < line.length(); i++) {
                char c = line.charAt(i);
                int xleft = i * dest.getWidth() / line.length();
                int xright = (i+1) * dest.getWidth() / line.length();
                int ytop = j * dest.getHeight() / tab.size();
                int ybottom = (j+1) * dest.getHeight() / tab.size();
                int x = (xleft + xright) / 2;
                int y = (ytop + ybottom) / 2;
                if (c == '|') {
                    drawLine(dest, x, ytop, x, ybottom);
                }
                if (c == '-') {
                    drawLine(dest, xleft, y, xright, y);
                }
                if (c == 'L') {
                    drawLine(dest, x, y, xright, y);
                    drawLine(dest, x, y, x, ytop);
                }
                if (c == 'J') {
                    drawLine(dest, x, y, xleft, y);
                    drawLine(dest, x, y, x, ytop);
                }
                if (c == 'r') {
                    drawLine(dest, x, y, xright, y);
                    drawLine(dest, x, y, x, ybottom);
                }
                if (c == 'g') {
                    drawLine(dest, x, y, xleft, y);
                    drawLine(dest, x, y, x, ybottom);
                }
            }

        }

        ImageIO.write(dest, "png", new File("output.png"));

    }


    private static void drawLine(BufferedImage dest, int x1, int y1, int x2, int y2) {
        int dist = Math.max(Math.abs(x1 - x2), Math.abs(y1 - y2));
        for (int i = 0; i <= dist; i++) {
            int x = (x1*(dist - i) + x2 * i) / dist;
            int y = (y1*(dist - i) + y2 * i) / dist;
            dest.getRaster().setPixel(x, y, new int [] {0, 0, 0});
        }
    }

    private static void expand(BufferedImage src, List<String> tab, String p1, String p2, String r1, String r2, boolean choose) {
        for (int k = 0; k < (choose ? 2 : 1); k++) {
            while (true) {
                boolean again = false;
                for (int j = 0; j < tab.size() - 1; j++) {
                    String line1 = tab.get(j);
                    String line2 = tab.get(j+1);
                    int baseScore = evaluateLine(src, j, tab.size(), line1) + evaluateLine(src, j+1, tab.size(), line2);
                    for (int i = 0; i <= line1.length() - p1.length(); i++) {
                        if (line1.substring(i, i + p1.length()).equals(p1)
                                && line2.substring(i, i + p2.length()).equals(p2)) {
                            String nline1 = line1.substring(0,  i) + r1 + line1.substring(i + p1.length());
                            String nline2 = line2.substring(0,  i) + r2 + line2.substring(i + p2.length());
                            int nScore = evaluateLine(src, j, tab.size(), nline1) + evaluateLine(src, j+1, tab.size(), nline2);
                            if (!choose || nScore > baseScore) {
                                tab.set(j, nline1);
                                tab.set(j+1, nline2);
                                again = true;
                                break;
                            }
                        }
                    }
                    if (again) break;
                }
                if (!again) break;
            }
            String tmp1 = r1;
            String tmp2 = r2;
            r1 = p1;
            r2 = p2;
            p1 = tmp1;
            p2 = tmp2;
        }
    }

    private static int evaluateLine(BufferedImage src, int j, int tabSize, String line) {
        int [] color = {0, 0, 0};
        int score = 0;
        for (int i = 0; i < line.length(); i++) {
            char c = line.charAt(i);
            int x = i*src.getWidth() / line.length();
            int y = j*src.getHeight() / tabSize;
            src.getRaster().getPixel(x, y, color);
            if (c == ' ' && color[0] >= 128) score++;
            if (c != ' ' && color[0] < 128) score++;
        }
        return score;
    }



    private static List<String> iterate(BufferedImage src, List<String> tab, boolean choose) {
        int [] color = {0, 0, 0};
        List<String> tab2 = new ArrayList<String>();
        for (int j = 0; j < tab.size(); j++) {
            String line = tab.get(j);
            String l1 = "", l2 = "", l3 = "";
            for (int i = 0; i < line.length(); i++) {
                char c = line.charAt(i);
                List<String []> candidates = replace(c);
                String [] choice = null;
                if (choose) {

                    int best = 0;
                    for (String [] candidate : candidates) {
                        int bright1 = 0;
                        int bright2 = 0;
                        for (int j1 = 0; j1<3; j1++) {
                            int y = j*3+j1;
                            for (int i1 = 0; i1<3; i1++) {
                                int x = i*3+i1;
                                char c2 = candidate[j1].charAt(i1);
                                src.getRaster().getPixel(x*src.getWidth()/(line.length()*3), y*src.getHeight()/(tab.size()*3), color);
                                if (c2 != ' ') bright1++;
                                if (color[0] > 128) bright2++;
                            }
                        }
                        int score = Math.abs(bright1 - bright2);
                        if (choice == null || score > best) {
                            best = score;
                            choice = candidate;
                        }

                    }
                } else {
                    choice = candidates.get(0);
                }
                //String [] r = candidates.get(rand.nextInt(candidates.size()));
                String [] r = choice;
                l1 += r[0];
                l2 += r[1];
                l3 += r[2];
            }
            tab2.add(l1);
            tab2.add(l2);
            tab2.add(l3);
        }
        return tab2;
    }

    private static List<String []> replace(char c) {
        if (c == 'r') {
            return Arrays.asList(
                    new String[] {
                    "r-g",
                    "| L",
                    "Lg "},
                    new String[] {
                    "   ",
                    " r-",
                    " | "}, 
                    new String[] {
                    "   ",
                    "r--",
                    "Lg "}, 
                    new String[] {
                    " rg",
                    " |L",
                    " | "},
                    new String[] {
                    "   ",
                    "  r",
                    " rJ"});            
        } else if (c == 'g') {
            return Arrays.asList(
                    new String[] {
                    "r-g",
                    "J |",
                    " rJ"},                 
                    new String[] {
                    "   ",
                    "-g ",
                    " | "},
                    new String[] {
                    "   ",
                    "--g",
                    " rJ"},
                    new String[] {
                    "rg ",
                    "J| ",
                    " | "},
                    new String[] {
                    "   ",
                    "g  ",
                    "Lg "});
        } else if (c == 'L') {
            return Arrays.asList(
                    new String[] {
                    "rJ ",
                    "| r",
                    "L-J"},
                    new String[] {
                    " | ",
                    " L-",
                    "   "},
                    new String[] {
                    "rJ ",
                    "L--",
                    "   "},
                    new String[] {
                    " | ",
                    " |r",
                    " LJ"},
                    new String[] {
                    " Lg",
                    "  L",
                    "   "});
        } else if (c == 'J') {
            return Arrays.asList(
                    new String[] {
                    " Lg",
                    "g |",
                    "L-J"},
                    new String[] {
                    " | ",
                    "-J ",
                    "   "},
                    new String[] {
                    " Lg",
                    "--J",
                    "   "},
                    new String[] {
                    " | ",
                    "g| ",
                    "LJ "},
                    new String[] {
                    "rJ ",
                    "J  ",
                    "   "});
        } else if (c == '-') {
            return Arrays.asList(
                    new String[] {
                    " rg",
                    "g|L",
                    "LJ "},
                    new String[] {
                    "rg ",
                    "J|r",
                    " LJ"},
                    new String[] {
                    "   ",
                    "---",
                    "   "},
                    new String[] {
                    "r-g",
                    "J L",
                    "   "},
                    new String[] {
                    "   ",
                    "g r",
                    "L-J"},
                    new String[] {
                    "rg ",
                    "JL-",
                    "   "},
                    new String[] {
                    " rg",
                    "-JL",
                    "   "},                 
                    new String[] {
                    "   ",
                    "gr-",
                    "LJ "},
                    new String[] {
                    "   ",
                    "-gr",
                    " LJ"}                                      
                    );                      
        } else if (c == '|') {
            return Arrays.asList(
                    new String[] {
                    " Lg",
                    "r-J",
                    "Lg "},
                    new String[] {
                    "rJ ",
                    "L-g",
                    " rJ"},
                    new String[] {
                    " | ",
                    " | ",
                    " | "},
                    new String[] {
                    " Lg",
                    "  |",
                    " rJ"},
                    new String[] {
                    "rJ ",
                    "|  ",
                    "Lg "},
                    new String[] {
                    " Lg",
                    " rJ",
                    " | "},
                    new String[] {
                    " | ",
                    " Lg",
                    " rJ"},
                    new String[] {
                    "rJ ",
                    "Lg ",
                    " | "},
                    new String[] {
                    " | ",
                    "rJ ",
                    "Lg "}                  
                    );
        } else {
            List<String []> ret = new ArrayList<String []>();
            ret.add(
                    new String[] {
                    "   ",
                    "   ",
                    "   "});
            return ret;
        }

    }
}

2
এটি এখনও অবধি সবচেয়ে উদ্ভাবনী সমাধানগুলির মতো দেখায়! ব্যাটম্যান জন্য +1 =)
flawr

আমি এটাকে ভালবাসি.
ট্রাইকোপলাক্স
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.