Soma de gráficos coloridos

9

Em alguns casos, geralmente na física, você precisa somar gráficos. Seu desafio é escrever, em um idioma de sua escolha, um programa ou função que tome vários gráficos como imagens, calcule todas as somas possíveis e produza o resultado.

Gráficos

Os gráficos são imagens que contêm um fundo branco ( rgb(255, 255, 255)) com um pixel não branco em cada coluna. Exemplos:

gráfico de exemplo gráfico de exemplo gráfico de exemplo

Os valores do script são representados como as posições Y dos pixels coloridos. O valor em uma determinada coordenada X é igual à posição Y do pixel colorido mais alto nessa coluna, com coordenadas começando em 0 no canto inferior esquerdo. Pode ou não haver pixels coloridos adicionais abaixo desses pixels por motivos estéticos.

Tarefa

Sua tarefa é escrever, em um idioma de sua escolha, um programa ou função que tome vários gráficos como imagens, calcule todas as 2^n - 1somas possíveis e produza o resultado.

Uma soma de gráficos é um gráfico em que o valor de cada coluna é igual à soma dos valores da coluna correspondente em cada um dos gráficos de entrada.

Os gráficos virão em várias cores. A imagem resultante deve conter todas as somas possíveis dos gráficos como outros gráficos, incluindo os gráficos originais, mas excluindo a soma zero.

A cor de cada soma é determinada pela média das cores dos gráficos incluídos, por exemplo, gráficos de cores rgb(255, 0, 255)e rgb(0, 255, 255)produziria um gráfico de rgb(128, 128, 255)(também pode ser arredondado para baixo).

A imagem resultante deve ter o tamanho necessário para caber em todos os gráficos. Isso significa que você pode ter que produzir uma imagem maior que qualquer uma das entradas.

A ordem na qual os gráficos resultantes são desenhados para a imagem resultante não importa, ou seja, se os gráficos de resultados se sobrepõem, você pode escolher qual deles está no topo, mas deve ser um dos gráficos, não uma combinação de cores.

Você pode assumir que as imagens de entrada têm largura igual, que todas as colunas das imagens têm pelo menos um pixel não branco e que as alturas das imagens (incluindo a saída) estão abaixo de 4096 pixels.

Exemplo

Entrada A:

exemplo gráfico a

Entrada B:

exemplo gráfico b

Exemplo de saída:

soma do gráfico de exemplo

(Caso alguém esteja interessado, copiei os dados para esses dados nos gráficos de ações de empresas aleatórias. Foi a primeira maneira que encontrei para obter dados realistas como CSV.)

Regras

  • Você pode escolher qualquer formato de arquivo de entrada de imagem de bitmap.
  • Você pode escolher qualquer formato de arquivo de saída de imagem de bitmap, que não precise corresponder à entrada.
  • Você pode usar bibliotecas de processamento de imagens, no entanto, qualquer função para concluir esta tarefa diretamente é banida.
  • Aplicam-se brechas padrão .
  • Isso é , então o código mais curto em bytes vence.

Script gerador de gráfico

Aqui está um script Python 2 que gera gráficos. A entrada é dada em linhas, com as três primeiras linhas como a cor RGB e o restante como dados, finalizadas pelo EOF.

import PIL.Image as image
import sys

if len(sys.argv) < 2:
    sys.stderr.write("Usage: graphgen.py <outfile> [infile]")
    exit(1)
outfile = sys.argv[1]
if len(sys.argv) > 2:
    try:
        stream = open(sys.argv[2], "r")
        data = stream.read()
        stream.close()
    except IOError as err:
        if err.errno == 2:
            sys.stderr.write("File \"{0}\" not found".format(sys.argv[2]))
        else:
            sys.stderr.write("IO error {0}: {1}".format(err.errno, err.strerror))
        exit(1)
else:
    data = sys.stdin.read()

try:
    items = map(int, data.strip().split("\n"))
    red, green, blue = items[:3]
    items = items[3:]
    highest = max(items)
except (ValueError, TypeError, IndexError):
    sys.stderr.write("Invalid value(s) in input")

img = image.new("RGB", (len(items), highest + 1), (255, 255, 255))

prev = items[0]
img.putpixel((0, highest - items[0]), (red, green, blue))
for x, item in enumerate(items[1:]):
    img.putpixel((x + 1, highest - item), (red, green, blue))
    if item < prev:
        for i in range(item + 1, prev):
            img.putpixel((x, highest - i), (red, green, blue))
    else:
        for i in range(prev + 1, item):
            img.putpixel((x + 1, highest - i), (red, green, blue))
    prev = item

img.save(outfile, "png")
PurkkaKoodari
fonte
@ MartinBüttner Atualmente, estou criando um para dois gráficos. Eu estou fazendo isso manualmente (sem nenhum implemento de referência), então não sei se tenho paciência para 3. Além disso, os três que dei não podem ser somados, pois têm larguras diferentes.
PurkkaKoodari
Então, se houver ngráficos de entrada, haverá 2^n - 1linhas na imagem de saída?
Peter Taylor
@PeterTaylor Sim.
PurkkaKoodari
Presumo que a saída não precise conter linhas verticais? Apenas o pixel mais alto de cada coluna?
Martin Ender
@ MartinBüttner Isso está correto, pois esses dados ainda podem ser analisados ​​como um gráfico, conforme definido na primeira seção.
PurkkaKoodari

Respostas:

3

MATLAB, 405

Ligar via: f('http://i.stack.imgur.com/ffCzR.png','http://i.stack.imgur.com/zHldg.png')

function f(varargin)
for k=1:nargin
i=im2double(imread(varargin{k}))
V(k,:)=size(i,1)-cellfun(@(V)find(any(V~=1,3),1),num2cell(i,[1,3]))
C(k,:)=i(find(any(i(:,1,:)~=1,3),1),1,:)
end
s=2^nargin-1
G=dec2bin(1:s)-'0'
C=bsxfun(@rdivide,G*C,sum(G,2))
V=G*V
m=max(V(:))
r=ones(m+1,size(V,2))
g=r
b=r
for i=1:s
M=bsxfun(@eq,(m:-1:0).',V(i,:))
r(M)=C(i,1)
g(M)=C(i,2)
b(M)=C(i,3)
end
imwrite(cat(3,r,g,b),'S.png')
knedlsepp
fonte
4

Python, 422

Ligar da linha de comando python plotsum im1.png im2.png im3.png

import sys
from numpy import*
from scipy import misc as m
R=m.imread
r=range
a=array
N=sys.args[1:]
L=len(N)
P=[map(argmin,R(n,1).T)for n in N]               #converts image to list of heights, counting from the top
C=a([R(N[i])[P[i][0],0,:]for i in r(L)])         #finds and stores the colour
P=a([len(R(N[i]))-a(P[i])for i in r(L)])         #flips the numbers, measures actual heights from bottom
w=len(P[0])
h=max(sum(P,0))+1                                    #compute dimensions
G=ones((h,w,3))*255                                  #and make a white grid
for i in r(1,2**L):
 z=where(a(list(bin(i)[2:].zfill(L)))=='1');y=sum(P[z],0)    #sum the graphs
 for x in r(w):G[y[x],x,:]=average(C[z],0)                   #average the colours
m.imsave('S.png',G[::-1])                            #flip image vertically and save

Exemplo de saída
insira a descrição da imagem aqui
Outro exemplo
insira a descrição da imagem aqui

Essa foi uma tarefa complicada, operações de matriz de alto nível e o uso de matrizes como índices ajuda muito aqui. Não espero ver soluções com menos de 1000 bytes, exceto no Mathematica e no Matlab

DenDenDo
fonte