quinta-feira, 9 de janeiro de 2020

Emprego do Linq Parte1

Recebi um teste para resolver algumas questões e quero mostrar as soluções.

LINQ

Seja uma classe

List employee = new List()
{
 new Employee() { Name = "John", Salary = 2500, Bonus = 100 },
 new Employee() { Name = "Ed", Salary = 3000, Bonus = 100 },
 new Employee() { Name = "Taylor", Salary = 2650, Bonus = 150 },
 new Employee() { Name = "Mike", Salary = 1580, Bonus = 120 },
 new Employee() { Name = "Ted", Salary = 1950, Bonus = 150 },
 new Employee() { Name = "Adam", Salary = 2300, Bonus = 0 },
};

1. Implemente um método que retorne a média salarial desta lista.
2. Retorne os nomes das pessoas que ganham acima da média.
3. Faça uma nova lista que retorne a soma do salário e do bonus.
4. Aproveitando o item anterior, retorne uma nova lista das pessoas que ganham abaixo da média (salário + bonus) e acrescente 15%.

Solução:

Para manipular uma lista com 3 colunas foi preciso fazer a classe Employee e o conteúdo foi:

    class Employee
    {
        public string Name { get; set; }
        public double Salary { get; set; }
        public double Bonus { get; set; }
    }

Para manipular uma lista com 2 colunas foi preciso fazer a classe NomeSalario e o conteúdo foi:

    class NomeSalario
    {
        public string Name { get; set; }
        public double SalarioTotal { get; set; }
    }

O código-fonte completo no método Main() está abaixo:

static void Main(string[] args)
{
 List employee = new List()
 {
  new Employee() { Name = "John", Salary = 2500, Bonus = 100 },
  new Employee() { Name = "Ed", Salary = 3000, Bonus = 100 },
  new Employee() { Name = "Taylor", Salary = 2650, Bonus = 150 },
  new Employee() { Name = "Mike", Salary = 1580, Bonus = 120 },
  new Employee() { Name = "Ted", Salary = 1950, Bonus = 150 },
  new Employee() { Name = "Adam", Salary = 2300, Bonus = 0 },
 };

 Console.WriteLine("A média salarial é {0}", GetMeanSalary(employee));
 Console.WriteLine("Os funcionários que ganham acima da média são: ");
 var nomeSalarioAcimaMedia = NamesAboveMeanSalary(employee);
 foreach (var item in nomeSalarioAcimaMedia)
 {
  Console.WriteLine(item.Name);
 }


 Console.WriteLine("\nA lista com nomes e salário total é: ");
 var nomeSalario = SumSalaryBonus(employee);
 foreach (var item in nomeSalario)
 {
  Console.WriteLine("{0,-7} {1,10}", item.Name, item.SalarioTotal);
 }
 
 Console.WriteLine("A média (salário + bonus) é: {0:C2}\n", GetMeanSalary(nomeSalario));
 
 Console.WriteLine("As pessoas que ganham abaixo da média e tiveram reajuste de 15% são: ");
 var listaReajustada = GetTotalSalaryBelowMeanApply15percent(nomeSalario);
 foreach (var item in listaReajustada)
 {
  Console.WriteLine("{0,-7} {1,10}", item.Name, item.SalarioTotal);
 }
}

static double GetMeanSalary(List lista)
{
 return lista.Sum(x => x.Salary) / lista.Count();
}

static List NamesAboveMeanSalary(List lista)
{
 return lista.Where(x => x.Salary > GetMeanSalary(lista)).ToList();
}

static List SumSalaryBonus(List lista)
{
 List nomeSal = new List();
 foreach (var item in lista)
 {
  nomeSal.Add(new NomeSalario() { Name = item.Name, SalarioTotal = item.Salary + item.Bonus});
 }
 return nomeSal;
}

static double GetMeanSalary(List lista)
{
 return lista.Sum(x => x.SalarioTotal) / lista.Count();
}

static List GetTotalSalaryBelowMeanApply15percent(List lista)
{
 var abaixoMediaSalarioTotal = lista.Where(x => x.SalarioTotal < GetMeanSalary(lista));
 foreach (var item in abaixoMediaSalarioTotal)
 {
  item.SalarioTotal = item.SalarioTotal * 1.15;
 }
 return lista;
}

A saída do programa da implementação é:

A média salarial é 2330
Os funcionários que ganham acima da média são:
John
Ed
Taylor

A lista com nomes e salário total é:
John          2600
Ed            3100
Taylor        2800
Mike          1700
Ted           2100
Adam          2300
A média (salário + bonus) é: R$2.433,33

As pessoas que ganham abaixo da média e tiveram reajuste de 15% são:
John          2600
Ed            3100
Taylor        2800
Mike          1955
Ted           2415
Adam          2645


Conceitos

1. Sem citar código/tecnologia defina o que é abstração. Cite um exemplo.
2. O que é herança? Quais as vantagem de usá-la?
3. O que é polimorfismo?
4. O que é classe e o que é objeto?

O que é débito técnico?

Git

Se você tem uma branch chamada task1234 e quer fazer um merge com a branch master, qual o procedimento?

a) Estar na branch task1234 e digitar git merge master
b)
c)
d) Estar na branch master e digitar git merge task1234

O stash tem uma estrutura de dados:

a) Fila
b)
c) Pilha
d) Árvore

quinta-feira, 26 de dezembro de 2019

Git e Github

Git e Github para iniciantes

https://www.udemy.com/course/git-e-github-para-iniciantes

Aula 6 - Configuração inicial do Git

Configurando o sistema

$ git config --global user.name "Murilo Fujita"
$ git config --global user.email "murilofujita@gmail.com"

Configurar o editor de texto

$ git config --global core.editor sublime/vim/emacs

Verificando qual o valor atribuído
$ git config user.name
$ git config user.email

Listando todos os valores atribuídos na configuração
$ git config --list

Aula 7 - Inicializando um repositório

Crie um diretório
$ mkdir myGithub

Entre neste diretório
$ cd myGithub

Inicie o monitoramento dos arquivos a partir deste diretório-raiz
$ git init

Aula 9 - O ciclo de vida dos status de seus arquivos

Estados dos arquivos no ciclo de vida

Untracked → Unmodified → Modified → Staged

  • Untracked: não é rastreado e o git desconhece sua existência
  • Unmodified: Não teve modificação
  • Modified: Arquivo que teve modificação
  • Staged: arquivo afetado pelo comando commit.

Um commit é a criação de uma imagem dos arquivos que estão sendo monitorados pelo git.

Adicione o(s) arquivo(s) que serão monitorados pelo git:
$ git add readme.md

Faça o commit:
$ git commit -m "Primeiro commit."

Observação 1: sempre analise o cenário com o comando git status.

Observação 2: caso apareça a mensagem:

On branch master
Changes not staged for commit:
        modified:   readme.md

Significa que nada foi adicionado para acontecer o commit. Corrija através do comando
$ git add [arquivo]

para só então realizar o commit:
$ git commit -m "nova descrição"

Aula 10 - Visualizando logs

Visualize o histórico dos commits.
$ git log

commit 1fed672a9473d092d401d3238fb4f77139cf63fa (HEAD -> master)
Author: Murilo Fujita 
Date:   Wed Dec 18 19:52:45 2019 -0300

    atualizado 1.

commit 380e8296c40f9f9c17dcb05c2984f0f64f6a44d7
Author: Murilo Fujita 
Date:   Wed Dec 18 19:44:06 2019 -0300

    Primeiro commit.

Algumas variações da visualização dos logs.
$ git log --decorate
$ git log --author="Murilo Fujita"

Comando para visualizar de forma resumida o autor e as mensagens de commits.
$ git shortlog

Comando para visualizar de forma resumida apenas o nome e a quantidade.
$ git shortlog -sn

Git exibindo as branches
$ git log --graph

Se quiser detalhes específicos do commit, digite o comando git log e em seguida copie a hash do commit desejado
$ git show [hash]

Aula 11 - Visualizando o diff

Estes comandos são feitos antes de realizar o commit. Desta forma é possível saber quais foram as mudanças antes de realizar o commit.

As linhas na cor verde (sinal de + no início da linha) indicam quais foram adicionadas.
$ git diff

Para saber somente os arquivos que foram modificados
$ git diff --name-only

Observação: Caso já tenha colocado na área de staged, o git diff não mostra diferenças.

Aula 12 - Desfazendo as coisas

Este comando é válido somente se houve alterações no arquivo e logo em seguida desistiu do que fez (não fez "git add [arquivo]").
$ git checkout [arquivo]

Caso já tenha colocado na área de stage através do comando "git add [arquivo]", o comando é:
$ git reset HEAD [arquivo]
$ git reset HEAD readme.md
Unstaged changes after reset:
M readme.md Geralmente se quis remover o arquivo da área staged, também quer desfazer as modificações do arquivo. Então:
$ git checkout [arquivo]

Nesta situação, o commit foi feito. 3 níveis de desfazer.

  • soft: elimina o commit, mas o arquivo permanece na área de staged (depois do git add e antes do git commit).
    • staged → modified
  • mixed: elimina o commit e deixa o arquivo antes do git add (modified da cor verde).
    • staged → unmodified
  • hard: extermina tudo que foi feito (modified da cor vermelha). O arquivo local ainda tem a alteração feita.
    • staged → untracked

Observação: a hash escolhida deve ser a do commit específico (voltar 1, 2 ou n posições do histórico).
$ git reset --hard 1e73c557f51f75750f57be7a21e357b12fdae83c
HEAD is now at 1e73c55 Esta é a aula 12.

Observação: usar o reset --hard causará a seguinte situação: o git mostrará diferenças entre o está no remoto e o que você tem (local). A única forma de atualizar deixando-os iguais é através do parâmetro force.

Aula 13 - Criando um repositório no Github

Todas as instruções do quick setup apareceram quando não foi colocado não selecionado para criar o arquivo readme.

Aula 14 - Criando e Adicionando uma chave SSH

Aula 15 - Ligando repositório local a um remoto

$ git remote add origin https://github.com/mfujita/myGithub.git

Nome do repositório padrão ao qual local e remoto estão ligados
$ git remote

origin

Informações mais detalhadas
$ git remote -v

origin  https://github.com/mfujita/myGithub.git (fetch)
origin  https://github.com/mfujita/myGithub.git (push)

Enviando logs e demais informações para o repositório remoto.
$ git push -u origin master

Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 4 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (9/9), 806 bytes | 403.00 KiB/s, done.
Total 9 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/mfujita/myGithub.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

Aula 16 - Enviando mudanças para um repositório remoto

$ git push origin master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 298 bytes | 298.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/mfujita/myGithub.git
   1e73c55..4498c53  master -> master

Aula 17 - Clonando repositórios remotos

Clonando através de HTTPS
$ git clone https://github.com/mfujita/myGithub.git [nome_do_seu_projeto]

Clonando através de SSH
$ git clone git@github.com:mfujita/myGithub.git [nome_do_seu_projeto]

Aula 25 - Criando o .gitignore

Crie um arquivo denominado .gitignore e configure para determinar quais arquivos não serão monitorados pelo git.

Pode ser pela extensão ou o nome específico do arquivo.

Para um modelo completo acesse https://github.com/github/gitignore

domingo, 12 de novembro de 2017

Selecionando arquivos de 6 em 6 ou outros intervalos

Quando os nomes dos arquivos estão sequenciados (000, 001, 002, 003, ...) e há necessidade de alguma ação como copiar determinados arquivos para outro diretório, um script resolve o problema.

Inicialmente todos os arquivos são listados pelo comando ls *.jpg e lidos pelo while. Nomes dos arquivos: z0001.jpg, z0002.jpg, z0003.jpg, ...

A variável file armazena o nome do arquivo a partir da segunda posição e elimina ".jpg".
Por exemplo, o nome z0001.jpg torna-se 001, z0002.jpg torna-se 002 e assim por diante.

Para eu obter somente os arquivos múltiplos de 6, a variável calc armazena o resto da divisão por 6.

O comando de decisão if verifica os arquivos que são múltiplos de 6 e copia para outro diretório.

Caso queria de 5 em 5 ou qualquer outro intervalo, modifique a linha que contém a variável calc.

#!/bin/bash

ls *.jpg | { 
  while read arq 
    do
      file="`echo $arq | cut -c 2- | sed 's/.jpg//'`"
      calc=`echo "$file % 6" | bc`
      if [ $calc == 0 ]
        then
          cp -v $arq de6em6
      fi
done
}

quarta-feira, 19 de outubro de 2016

Procurando texto em arquivos de diversos diretórios

Faço uso de mala direta e uso as ferramentas que criei para propósitos diferentes como comunicar o número de faltas, divulgar notas de trabalhos e provas bem como emitir comunicados com meus alunos.

Às vezes os alunos mudam o endereço de e-mail e preciso atualizar em todos os meus programas. Como procurar todas as ocorrências nos arquivos que estão espalhado em diversos diretórios?

Acompanhe o shell script a seguir no qual a aluna Rosalia pediu para receber meus comunicados em outro endereço de e-mail.

#!/bin/bash
find . -name \*.cs -exec ls {} \; > arquivosCS.txt
linhas=`wc -l arquivosCS.txt | awk '{printf "%s\n",$1}'`

for i in `seq $linhas`
  do
    grep -i rosalia `head -n $i arquivosCS.txt | tail -n 1` > /dev/null
    if [ $? == 0 ]
      then 
        echo `head -n $i arquivosCS.txt | tail -n 1`
    fi
  done
  

Os passos são:

  1. Fazer o levantamento de todos os arquivos que têm códigos-fontes (extensão .cs)
  2. Determinar quantos arquivos têm a extensão cs
  3. Executar o for para analisar cada arquivo (combinando head e tail)
  4. Se o nome da pessoa está naquele arquivo (comando grep), então $? retorna 0 (zero) que é o mesmo que verdadeiro.
  5. O que for verdadeiro, faço que exiba o arquivo com o comando echo.

A instrução > /dev/null direciona a saída para o dispositivo que anula seu efeito, ou seja, não imprime a saída.

Este script deve ser executado no diretório que contém todos os arquivos relevantes da sua busca, ou seja, será feita a busca em todos os níveis a partir do ponto onde é executado.

A saída abaixo gerou uma listagem de todos os arquivos que tenho que fazer as modificações:

./faltas2016s2/faltas2016s2/faltas2016s2/FaltaAlunos.cs
./RHMatFinEstatistica2016/RHMatFinEstatistica2016/RHMatFinEstatistica2016/MalaDireta.cs   
  

Conclusão: Funciona muito bem e recomendo que adote a ferramenta ao invés de confiar na memória acreditando que modificou em todos os arquivos necessários.

quinta-feira, 5 de fevereiro de 2015

Usando curl para acessar dados do roteador

Uma das minhas preocupações é a de saber quantas e quais máquinas estão conectadas à minha rede. Para este propósito tenho que acessar o roteador pelo browser, realizar a autenticação preenchendo os campos usuário e senha e por fim entrar na página que fornece o recurso de listar quem está nos meus domínios.

Um bom shell script tem a vantagem de substituir muito bem esta questão da segurança, mas a desvantagem de não entregar a resposta formatada como as páginas HTML neste caso. É claro que os dados podem ser tratados e criar uma página HTML elaborada.

Antes de abordar o comando, exportei os valores da variável pelo arquivo .bashrc por questões de segurança. Você pode usar o nome de login e senha explicitamente na linha de comando que funcionará da mesma forma.

Finalmente, o comando usado é o curl.

curl -b -c -u $user:$pass http://192.168.xx.xx/Status/st_session.htm | grep 192.

A opção -b transfere a informação para o servidor HTTP como um cookie.
A opção -c armazena este cookie.
A opçao -u informa o nome de usuário e senha separados por dois pontos (:).

Em seguida o endereço URL e saída dele é jogada para o grep que busca os IPs que començam com 192 que é o meu intervalo de IPs.

Como a resposta é muito confusa, acrescentei mais alguns comandos:

  • substituição do símbolo "[" por "pular linha"
  • substituição do símbolo "," por espaço em branco.
  • exibir o segundo campo
  • ordenar de forma crescente
  • exibir os resultados distintos

O comando completo é:

curl -b -c -u $user:$pass http://192.168.xx.xx/Status/st_session.htm | grep 192. | tr "[" "\n" | sed 's/,/ /g' | cut -f2 -d" " | sort | uniq

Algumas estatísticas aparecem, mas o essencial está feito. Levo um tempo insignificante em comparação com o uso do browser.

Obviamente será preciso que você substitua os valores da autenticação, as URLs e adeque os comandos para que a resposta fique legível.

quarta-feira, 17 de dezembro de 2014

Análise dos números da Mega Sena versão 2

Com o ganho de experiência, aprende-se a resolver os mesmos problemas de forma otimizada. Há um tempo foi apresentado o Análise dos números da Mega Sena e ao executar o mesmo script, resulta em erros porque a formatação dos dados foi alterada. Com algumas novas "sacadas", há uma nova versão disponível acompanhada dos comentários.

Com relação às melhorias, lista-se:

  • Saída sem exibir as respostas do unzip;
  • Ao invés de localizar um bloco que contém os números sorteados, localiza-se a data do sorteio e armazena-se as 6 linhas abaixo (as dezenas sorteadas);
  • Como consequência do item anterior, menos tags HTML para manipular.

Abaixo o shell script comentado mostrando a frequência de cada dezena sorteada e os 6 números mais frequentes.


#!/bin/bash
# Created in dez/26/2012 by murilofujita@gmail.com
# Modified in dez/14/2014
# Optimized in dez/16/2014

if [ -f D_mgsasc.zip ]
  then
    rm D_mgsasc.zip
fi

if [ -f T2.GIF ]
  then
    rm T2.GIF
fi

if [ -f /tmp/sena1.txt ]
  then
    rm /tmp/sena*.txt
fi

wget http://www1.caixa.gov.br/loterias/_arquivos/loterias/D_mgsasc.zip
unzip D_mgsasc.zip >& /dev/null

tr -d '\r' < d_megasc.htm > $$
mv $$ d_megasc.htm

ano_atual=`date +%Y`

# Quantidade de jogos realizados
for ano in `seq $ano_atual 1 $ano_atual`
    do
      jogo=`sed -n "/$ano/{x;p;};h" d_megasc.htm | sed 's/<[^>]*>//g'` 
    done 

# sorteios=`echo "$jogo"`
printf "Dados dos `echo "$jogo" | tail -n 1` sorteios"

# Obtendo os números sorteados
# "/ano" é a palavra para ser localizada. Se for apenas "ano" o numero 2000 pode aparecer 
# em outro campo. Por exemplo: 2000 é o número de ganhadores da quadra em 28/04/2004
  for ano in `seq 1996 1 $ano_atual` 
    do  
      awk "/\/$ano/ {for(i=1; i<=6; i++) {getline; print}}" d_megasc.htm 
    done > /tmp/sena1.txt

# Necessário remover as tags para que a massa de dados contenha apenas os números sorteados
sed 's/<[^>]*>//g' /tmp/sena1.txt > $$ 
mv $$ /tmp/sena1.txt

echo 
echo Exibindo a frequência dos números sorteados da Mega Sena
  for i in `seq 9`
    do
      printf "0$i `grep 0$i /tmp/sena1.txt | wc -l`  "
    done
  printf "10 `grep 10 /tmp/sena1.txt | wc -l` "
  printf "\n"

  for i in `seq 11 1 60`
    do
      printf "$i `grep $i /tmp/sena1.txt | wc -l`  "
      if [ $((i % 10)) -eq 0 ]
        then
          printf "\n"
      fi
    done
  printf "\n"

for i in `seq 9`; do printf "0$i `grep 0$i /tmp/sena1.txt | wc -l`\n" ; done >> /tmp/sena2.txt
for i in `seq 10 1 60`; do printf "$i `grep $i /tmp/sena1.txt | wc -l`\n" ; done >> /tmp/sena2.txt
awk '{printf "%3s %3s\n",$2, $1}' /tmp/sena2.txt | sort -n | tail -n 6 > /tmp/sena3.txt

echo Os números mais sorteados são:
echo Dezena Frequência

for i in `seq 6`
  do
     tail -n $i /tmp/sena3.txt | head -n 1 | awk '{printf "%4s %8s\n",$2, $1}'
  done

printf "\n"

awk '{printf "%s\n",$2}' /tmp/sena2.txt | paste -s -d"+"

if [ -f d_megasc.htm ]
  then
    rm d_megasc.htm
fi

Até a data de publicação foram realizados 1661 sorteios e o resultado é exibido abaixo:

Dados dos 1661 sorteios
Exibindo a frequência dos números sorteados da Mega Sena
01 159  02 170  03 157  04 192  05 196  06 163  07 168  08 170  09 143  10 176 
11 154  12 168  13 177  14 151  15 149  16 174  17 181  18 161  19 153  20 159  
21 145  22 137  23 178  24 182  25 148  26 137  27 169  28 176  29 175  30 170  
31 167  32 172  33 184  34 166  35 157  36 173  37 164  38 166  39 143  40 158  
41 175  42 184  43 178  44 173  45 151  46 160  47 170  48 150  49 179  50 173  
51 187  52 177  53 186  54 187  55 144  56 164  57 155  58 162  59 163  60 160  

Os números mais sorteados são:
Dezena Frequência
  05      196
  04      192
  54      187
  51      187
  53      186
  42      184

159+170+157+192+196+163+168+170+143+176+154+168+177+151+149+174+181+161+153+159+145+137+178+182+148+137+169+176+175+170+
167+172+184+166+157+173+164+166+143+158+175+184+178+173+151+160+170+150+179+173+187+177+186+187+144+164+155+162+163+160

A razão desta última linha é fazer uma checagem. Analise:

1661 sorteios * 6 números sorteados = 9966 números.

Basta copiar a linha do somatório e colar em uma calculadora ou célula de planilia eletrônica para verificar se coincide com a mesma quantidade dos números sorteados.

Conclusão: Por causa da diferença no formato da tabela, invalidou o primeiro script da "mega sena" e forçou uma otimização na forma de lidar com novo arquivo. O tempo de processamento diminuiu e é possível fazer uma verificação se todos os números foram contabilizados.

sábado, 24 de agosto de 2013

Preenchendo com zeros a esquerda para ordenar números


Um determinado arquivo contém números de 1 a 1045, mas foram gravados fora de ordem. Ao tentar ordená-lo com o comando

$ cat num.txt | sort

tive como resposta a listagem de todos os números que começam com 1, em seguida os que começam com 2 e assim por diante. Logo, não é a forma esperada e para resolver esta situação é preciso preencher com 0 (zero) até que cada número tenha 4 algarismos. Em outras palavras, ficará assim:

0001, 0002, ..., 0009, 0010, ..., 0099, 0100, ..., 0999, 1000, ..., 1045

O código-fonte que apresento desta vez é da linguagem C#. No IDE Visual Studio, abra um novo projeto e escolha o Template: Console Application. Esta opção chama o prompt de comando que é exclusivamente texto.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace AjeitaParaNumerar
{
    class Program
    {
        static void Main(string[] args)
        {
            int i, quantidade=0;
            Console.WriteLine("Este programa le um arquivo de nome num.txt e coloca 3 zeros se o numero for menor que 10, 2 zeros se maior do que 9 e menor do que 100 e por fim, 1 zero se maior do que 99 e moneor do que 1000.");
            StreamReader sr = new StreamReader("num.txt");

            string leitura;
            
     while ((leitura = sr.ReadLine()) != null)
            {
                quantidade++;
            }

            sr.Close();

            StreamWriter sw = new StreamWriter("ok.txt");
            sr = new StreamReader("num.txt");
            
            for (i = 0; i < quantidade; i++)
            {
                string[] valor = new string[quantidade];
                valor[i] = sr.ReadLine();
                if (Convert.ToInt32(valor[i]) < 10)
                {
                    valor[i] = valor[i].PadLeft(4, '0');
                    sw.WriteLine(valor[i]);
                }

                else if (Convert.ToInt32(valor[i]) > 9 && Convert.ToInt32(valor[i]) < 100)
                {
                    valor[i] = valor[i].PadLeft(4, '0');
                    sw.WriteLine(valor[i]);
                }

                else if (Convert.ToInt32(valor[i]) > 99 && Convert.ToInt32(valor[i]) < 1000)
                {
                    valor[i] = valor[i].PadLeft(4, '0');
                    sw.WriteLine(valor[i]);
                }


                else
                {
                    sw.WriteLine(valor[i]);
                }
            }

            sr.Close();
            sw.Close();
        }
    }
}

Mesmo que o código tenha sido desenvolvido em outro sistema operacional, é possível executá-lo no Linux. Para tal, instale o pacote mono-mcs e em seguida execute a linha de comando com o comando mcs com a seguinte sintaxe:

$ mcs fonte.cs -o nome_do_arquivo

Exemplificando supondo que eu escolhi que nome_do_arquivo seja ajeita.out:

$ mcs Program.cs -o ajeita.out

Como resultado, o arquivo ajeita.out não é executável e para torná-lo, basta usar o procedimento usual de dar permissão de execução:

$ chmod a+x ajeita.out

Finalmente, para executá-lo, faça simplesmente:

$ ./ajeita.out

Ao fim da execução, o arquivo ok.txt foi criado e seu conteúdo é a listagem dos 1045 números com quatro algarismos.

Conclusão: O projeto mono permite uma incrível portabilidade para o Linux. Há muitas facilidades por causa dos métodos prontos do C# e por esta razão, torna o desenvolvimento rápido e capaz de funcionar nos dois sistemas operacionais.

Adicionalmente, ao executar o comando para ordenar os números (cat ok.txt | sort), funcionou perfeitamente.