Desenhe com sua CPU

289

Encontrei um artigo em que os alunos usavam o tráfego de rede para desenhar sua universidade no gráfico IPv6 do país . [imagem]

Seu objetivo é simples de dizer, mas difícil de implementar. Desenhe o texto MAIL (como é uma das poucas palavras que podem ser lidas em um gráfico 1D) no gráfico da CPU.

Deve ser algo como isto:

Resultado

Elaborando um pouco mais sobre o que qualifica:

  • O código não precisa ser multiplataforma (portanto, você não precisará lidar com APIs desconhecidas).
  • Você pode capturá-lo em qualquer utilitário geral de uso da CPU que possui.
  • O gráfico parece um pouco pior em uma máquina diferente: confio em você neste momento.
  • O% de uso básico da CPU deve ser contínuo; portanto, se você gerar uma onda aleatória e destacar algo parecido com a palavra MAIL, obviamente isso é trapaça.
  • Você pode escolher a carga máxima a ser usada, mas precisa ser substancial o suficiente para vê-la claramente.
  • Você deve seguir a linearidade do exemplo. (Para M, é assim: base% e, em seguida, aumento repentino até o máximo especificado, diminua gradualmente para um% mais baixo, retorne ao máximo e queda repentina para o% base novamente.)
  • Se for ilegível, os eleitores perceberão, afinal.

Aplicam-se brechas padrão. Publique as imagens também!

bebe
fonte
9
Não vejo mais motivo para uma votação apertada. Pessoalmente, acho isso um desafio divertido, embora um pouco específico do sistema.
seequ
6
O problema que vejo com o código golf é julgar como legível é legível o suficiente. Se você puder pensar em uma maneira de especificar isso objetivamente, isso melhoraria bastante o desafio, mas é uma ótima idéia!
Martin Ender
3
é realmente igual à sua imagem, mas garanto que, se você não colocar em palavras, as pessoas interpretarão o "draw mail" de maneira muito liberal.
Martin Ender
33
+1, é tão absurdo que quase ri até a morte ... "isso é loucura ..." "loucura ... ESTE É CODEGOLF !!!"
vaxquis
5
Esta é uma pergunta incrível . Eu gostaria de ser inteligente o suficiente para participar. Isso realmente não importa, estou interessado nas soluções criativas por outras pessoas: P
Chris Cirefice

Respostas:

117

Python, 143

from time import*
while 1:
 sleep((ord('00012345654321000~~~D:6300036:D~~~000~~~000DDDD~~~~~'[int(time())%52])-48)*0.001);x=10**5
 while x:x-=1

Cada caractere da sequência corresponde a um segundo de atividade, do caractere ASCII 0(carga máxima) até a ~(carga muito leve). O programa é executado em um loop sincronizado com o tempo, para que você possa executar várias instâncias para obter melhores resultados.

Usei o Python 2.7.6 no OS X com um Intel Core i7, mas ele deve funcionar em outros computadores com alguns ajustes (ajuste o 0.001). A captura de tela abaixo foi tirada com significativa atividade em segundo plano.

ENVIAR

Atualização - Consegui produzir um gráfico mais claro time()/10e com uma frequência de atualização mais baixa:

ENVIAR

E, finalmente, aqui está uma versão mais prática ( 123 bytes ) e seu resultado :

from time import*
while 1:
 sleep((ord('002464200~~A5005A~~00~~00DDD~~'[int(time()/2)%30])-48)*0.001);x=10**5
 while x:x-=1
grc
fonte
250

Pitão, 358 281 268 221 194 bytes

Monocromático é tão no ano passado. Isso usa vários processos e syscalls para obter gráficos de CPU em duas cores !

import os,time
A='%-99o'%int('t12q2lxqkap48euoej9429cstbnazl63ubyryteo49u',36)
for i in'0123456':
 t=os.fork()
 while t<1:T=int(time.time())%50;(time.sleep,(id,os.urandom)[i<A[T+49]])[i<A[T]](1)

Saída do Activity Monitor (OS X 10.9):

Gráfico de Carga de CPU do Monitor de Atividade Gráfico do histórico da CPU do Monitor de Atividades

Repete-se no gráfico Histórico da CPU

Saída de MenuMeters:

Saída de MenuMeters

Todas as saídas foram geradas com uma velocidade de atualização de 1s. Nenhuma tarefa em segundo plano significativa estava em execução, embora essa saída supere com facilidade qualquer tarefa da CPU de thread único.

Este código supõe que você tenha 8 núcleos. Deve ser muito fácil modificar por menos / mais. É portátil para sistemas Linux / UNIX (embora tenha sido testado apenas no OS X) e deve produzir a mesma saída de duas cores para qualquer monitor de CPU que possa distinguir o tempo de CPU do usuário do sistema.

Essencialmente, isso funciona executando sete processos, cada um dos quais escolherá passar 1 segundo dormindo, girando no modo de usuário ou girando o kernel. A rotação no modo kernel é obtida solicitando grandes quantidades de dados /dev/urandom, o que força o driver /dev/urandoma gastar muitos ciclos de CPU do "sistema".

EDITADO [21/07]: Encurtado significativamente usando em fork()vez de multiprocessing.Process( /dev/urandomfunciona apenas em sistemas * NIX de qualquer maneira, portanto isso não reduz a portabilidade). Observe, no entanto, que o programa agora gera tarefas em segundo plano ; pode ser necessário killall Python(ou similar) para se livrar dos comedores de CPU.


Não pude resistir a implementar mais algumas cartas. Eu tenho 16 letras, mais alguns símbolos:

~ /._ PIN ANCHO ... ... VY

O alfabeto completo é "ACDFHILMNOPTUVWY", com os símbolos "._ ~ / \". Provavelmente há muito mais caracteres que podem ser representados.

Código totalmente não destruído para as letras extras:

from time import*
from multiprocessing import*

chars6 = {
'A': ('123456654321',
      '000123321000'),
'C': ('344556666666',
      '321110000000'),
'D': ('666666655443',
      '000000011123'),
'F': ('66666666666666',
      '00002222244444'),
'H': ('666664444466666',
      '000002222200000'),
'I': ('66666',
      '00000'),
'L': ('666662222222',
      '000000000000'),
'M': ('6665544334455666',
      '0004321001234000'),
'N': ('66665544336666',
      '00003322110000'),
'O': ('3445556666555443',
      '3221110000111223'),
'P': ('666666666555',
      '000003333444'),
'T': ('777776666677777',
      '444440000044444'),
'U': ('6666322236666',
      '4211000001124'),
'V': ('66654322345666',
      '33321000012333'),
'W': ('66542466424566',
      '43210133101234'),
'Y': ('66665433456666',
      '44333000033344'),
'_': ('1111111111',
      '0000000000'),
' ': ('000',
      '000'),
'.': ('12221',
      '10001'),
'~': ('44445544334444',
      '11223322112233'),
'/': ('2234566',
      '0012344'),
'\\': ('6654322',
       '4432100'),
}

s = 'ANCHOVY '
A = '000'.join(chars6[t][0] for t in s)
B = '000'.join(chars6[t][1] for t in s)

t=time()
f=open('/dev/urandom')
def F(n):
 while 1:T=int(time()-t)%len(A);[sleep,[].count,lambda x:f.read(4**9)][(n<int(A[T]))+(n<int(B[T]))](1)
for i in range(7):Process(target=F,args=(i,)).start()
F(7)
nneonneo
fonte
34
+1 para dar as cartas mais definição usando 2 cores
DustinDavis
4
E um para a criação de letra baseada em tabelas
GreenAsJade
1
O A pode de fato ser adequadamente renderizado (com um orifício) com 4 fios. Teria que definir algumas cores do monitor da CPU para coincidir.
Ruslan
@Ruslan: Em qual monitor de CPU você está pensando? Meu monitor mostra apenas um gráfico agregado, com 0 <= sistema <= usuário <= 100 em cada ponto (o que impossibilita o AFAIK de "buracos").
Nneonneo 12/07/2014
1
@nneonneo Quero dizer monitores semelhantes ao seu. Veja esta foto . Aqui, se mudarmos de azul para verde e vermelho e roxo para branco, obteremos um belo "A" com buracos.
Ruslan
133

C (Intel Core Duo + OS X / Darwin), 248 bytes

#include <unistd.h>
#include <mach/mach_time.h>
#define M mach_absolute_time()
main(){char*s="JJJIHGFGHIJJJ@BDFHJJJHFDB@JJJJ@JJJJBBBBBBB";uint64_t i,t,y=1;for(;*s;s++){
for(i=40;i;i--){for(t=M+(*s&15)*9090909;t>M;)y*=7;usleep((11-(*s&15))*9091);}}}

Esse código é tão portátil quanto a Grande Pirâmide de Quéops. Me desculpe por isso. Os valores retornados mach_absolute_time()dependem do hardware, mas na minha máquina o valor aumenta cerca de uma vez por nanossegundo.

Aqui está o resultado:

A palavra "MAIL" mostrada no meu gráfico de histórico de CPU

Existem dois gráficos porque o processador possui dois núcleos. Defino a carga máxima da CPU para cerca de 90% porque o processo pode alternar entre núcleos sempre que eu ligar usleep(). Com uma carga de 100%, o processo é acorrentado a um núcleo e os resultados são ilegíveis ( veja isso, por exemplo )

ossifrage melindroso
fonte
1
Bom trabalho! Isso parece muito interessante. Você poderia postar uma pequena explicação do código? :)
duci9y
1
eu vejo aparelhos. por que existem chaves nos loops for? você pode colocar usleep no segundo bloco final do loop. Eu acho que você pode jogar golfe um pouco mais facilmente.
7287 bebe
Não foi possível colocar a declaração e a inicialização das uint64_tvariáveis ​​no cabeçalho do seguinte forloop?
Joey
74
+1: "Este código é tão portátil quanto a Grande Pirâmide de Quéops"
Uwe Keim
Não, as variáveis ​​C devem ser declaradas no início de um bloco. colocá-lo no bloco de inicialização de for lançará um erro. é claro que só se aplica a <C99
bebe
102

Ruby, 150 caracteres

a=(0..15).map{|i|[0.9-3*i*=0.02,i]}
[9,*a[0,11],*(z=a.reverse)[5,11],11,*z,*a,2,11,6,*[0.2]*9].map{|x,y|c=Time.now
1until Time.now-c>x/3
sleep y||x%3}

Até agora, não é tão curto assim, mas, na minha opinião, a saída é bastante agradável, então achei que publicaria isso de qualquer maneira. Como na maioria das outras soluções, pode ser necessário fixar o processo Ruby em um determinado núcleo, prefixando-o com taskset -c $core.

O código é uma combinação simples de rotação / suspensão por um certo período de tempo, o que deve torná-lo um pouco portátil. Gradientes suaves são criados variando a proporção de rotação / tempo de sono.

Monitor de CPU escrito MAIL

Diminuir a frequência de amostragem da CPU torna as bordas um pouco melhores:

Frequência de amostragem mais baixa

Ao adicionar mais algumas letras ao alfabeto ( AILMNUVWsão um pouco reconhecíveis), também podemos escrever outras palavras:

MUM, MAW, VILLAIN

Essas imagens foram geradas com o seguinte código:

def gradient num_samples, direction, base = 0.3, increment = 0.02, scale = 1
    range = [*0..num_samples]

    samples = case direction
        when :up then range.reverse
        when :down then range
        when :updown then range.reverse + range
        when :downup then range + range.reverse
    end

    samples.map{|i|
        i *= increment
        [base - scale * i, i]
    }
end

# letters are defined as a series of pairs of (spin-time, sleep-time)
# with the time in seconds
THIN_A = gradient(15, :updown, 0.2, 0.2/15)
A = gradient(15, :updown)
I = 2,0
L = 1.5,0, [[0.1,0.2]]*9
M = 2,0, gradient(9, :downup), 2,0
N = 1,0, gradient(9, :down), 2,0
U = 1,0, gradient(9, :downup, 0.1, 0.03, 0.1), 1,0
V = 0.5,0, gradient(12, :downup, 0.25, 0.02), 0.5,0
W = 0.5,0, [gradient(12, :downup, 0.25, 0.02)]*2, 0.5,0

[A,I,L,M,N,U,V,W].map{|i|
    # add 2 second pause after each letter
    i + [0,2]
}.flatten.each_slice(2){|x,y|
    # spin, then sleep
    c = Time.now
    1 until Time.now-c > x
    sleep y
}

Palavras que podem ser escritas com as letras implementadas podem ser encontradas com

grep -E '^[aijlmnuvw]+$' /usr/share/dict/words 
Ventero
fonte
4
+1 para a extensão em mais palavras!
Chris Cirefice
Você poderia ter feito a palavra "alumínio".
Oliver Daugherty-Long
@ OliverDaugherty-Long aluminium *
TuxCrafting
1
@ TùxCräftîñg O alumínio é uma ortografia variante que tem uma letra extra e é a palavra mais longa que consigo pensar que funciona.
Oliver Daugherty-Long
48

Python, no Intel Pentium 4 3.0Ghz, 180 166 145 141 138 bytes

Ligue com taskset -c 0 python cpu_graph_drawer.py.

taskset é necessário para restringir o processo para usar apenas uma CPU / núcleo (hyperthreading no meu caso).

from time import*;c=clock
a=[(3,.8),(3,5),(4,5),(1.3,5),(1.3,0)]
a.extend([(.1,.2)]*10)
for x,y in a:
    t=c()
    while c()-t<x:pass
    sleep(y)

O resultado não é tão bom. Este com o conjunto de tarefas -c 1

user80551
fonte
9
Eu adoraria ver isso com um monitor de CPU que não suavizar as curvas ...
Szabolcs
1
Eu também, mas não tenho vontade de escrever um gráfico conky de uso da CPU e gnome-system-monitoré a única coisa que sei. Tem alguma alternativa que seria executada no LMDE Cinnamon?
user80551
Habilite o "Desenhar CPU como gráfico de área empilhada" e defina todas as cores para preto.
Tejas Kale
@TejasKale As linhas ainda seriam curvas.
user80551
FYI: você pode jogar um monte de caracteres usando em a=[...]+[(.1,.2)]*10vez de .extend.
Nneonneo 6/11
46

Java 8, 482 caracteres

Cada caractere na String significa o número de threads que serão utilizados. Imagem tirada no Intel Core i3 (2 núcleos / 4 threads).

resultado

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Mail{
public static void main(String[] args) throws InterruptedException{
Thread.sleep(15000);
for(char c:"123432234321000012343210000444000044441111111".toCharArray()){
ExecutorService executorService = Executors.newScheduledThreadPool(4);
for(int i=1;i<c-48;i++)executorService.execute(()->{while(!Thread.interrupted());});
Thread.sleep(1500);
executorService.shutdownNow();
}}}

Edit : versão mais golfe (322 caracteres), mesma funcionalidade:

import java.util.concurrent.*;
class M{
public static void main(String[]a)throws Exception{
for(int c:"123432234321000012343210000444000044441111111".toCharArray()){
ExecutorService s=Executors.newFixedThreadPool(4);
while(c>48){c--;s.execute(()->{while(!Thread.interrupted());});}
Thread.sleep(1500);
s.shutdownNow();
}}}
Tomáš Dvořák
fonte
1
Há um sinal de menos que foi interpretado como HTML e estragou a formatação.
David Conrad
@ValekHalfHeart próximas duas linhas devem explicar isso. Executor é um encadeamento (gerenciador de tarefas assíncronas) que executa tarefas (loops aqui) até a interrupção. Após criá-lo, o thread principal aguarda 1,5s e interrompe todas as tarefas.
PTwr
45
Ao abrir o Eclipse, meu gráfico de CPU escreveu "Simple Mail Transfer Protocol".
lolesque
21

C, 78 bytes

Você nunca disse que não podíamos aceitar a entrada do usuário, sooo ..

#include <unistd.h>
int main(){int x=0;for(;x<1<<26;++x);read(0,&x,1);main();}

Este programa lê desde o padrão e toda vez que lê um caractere, ele executa uma CPU gratuita que está desperdiçando o loop e depois chama o main novamente. Você controla a quantidade de tempo de CPU que ele usa enviando spam a tecla Enter em velocidades diferentes.

Eu executei isso em um intel i3 4130T, que é um processador razoavelmente novo. Mas sua milhagem pode variar, se estiver usando mais ou menos tempo de CPU do que o praticável para você observar, tente brincar com a quantidade de turnos no loop de atraso.

Meu programa é incrível porque:

  • é principalmente multiplataforma, deve funcionar com muito pouco em qualquer * nix
  • derrota a pergunta
  • ótimo jogo final

Depois de algumas tentativas, produzi um gráfico parecido com este:Gráfico da CPU

Wug
fonte
Ajuda a restringi-lo a um núcleo da CPU com o conjunto de tarefas, a.la. taskset -c 1 [file]
Wug
2
Eu não vejo nada nos requisitos de problema que diz nossas submissões será invocado comoyes | [program]
Wug
12
A brecha padrão ... também se enquadra em meta.codegolf.stackexchange.com/a/1085/6699 .
Nneonneo 14/07/2014
1
"ótimo jogo de final de jogo" me fez rir muito. +1
Christoph
1
Essa resposta é boa demais, lacunas sejam xD!
Urna de polvo mágico