Chris Maunder Ответов: 20

Задача кодирования: преобразование табуляций в пробелы


Ваша задача кодирования недели-простая. По крайней мере, так кажется.

Если задана текстовая строка, преобразуйте табуляции в пробелы. Вкладка предполагая, маркеры 4-х символов помимо

[ ][ ][tab]Hello, world!

становится
[ ][ ][ ][ ]Hello, World!


Где [ ] = пробел, [tab] = символ табуляции (я решил использовать их вместо "" и " "(или" \t"), чтобы легче было определить пробелы и табуляции.)

Еще один тестовый случай оставлен в качестве упражнения для читателя.
[ ][ ][ ][tab][tab][ ][tab]Hello, world!



Опять же: футболка, награжденная за дерзость, за стиль, за возмутительное использование неподобающих языков. В основном для входа, который развлекает нас больше всего.

Вызов на прошлой неделе Проблема кодирования: фильтр плохих слов[^] был выигран компанией PIEBALDConsult в категории" Боже, я скучаю по кодированию". Пошлите Sean @codeprject свой адрес и размер футболки, и рождественский подарок придет вам в голову.

Что я уже пробовал:

В основном, чтобы сохранять спокойствие.

Есть идея проблемы кодирования? Пришлите его мне по адресу chris@codeproject.com.

Afzaal Ahmad Zeeshan

Вы имеете в виду пробелы табуляции или просто табуляцию, как в символе?

CHill60

"возмутительное использование неподходящих языков" ... черт возьми, я собирался предоставить решение VB6, но потом вспомнил, что уничтожил установочные компакт-диски в ритуальном костре в прошлый Самайн

Graeme_Grant

Есть ли причина, по которой вы также переводите слова в заглавный регистр???

PIEBALDconsult

Был там, сделал это. Я воскрешу какой-нибудь древний код.

И не забудь об этой маленькой красавице...
https://www.codeproject.com/Articles/32593/Untabify-and-Tabify

Patrice T

Я думаю, что некоторые решения потерпят неудачу с:
"[ ][ ][ ][ ][ ][tab] Привет, мир!"

PIEBALDconsult

А что вы считаете правильным?

Patrice T

8 ведущих мест:
"[ ][ ][ ][ ][ ][ ][ ][ ]Здравствуй, мир!"

PIEBALDconsult

Я согласен. И мой должен это сделать.

20 Ответов

Рейтинг:
39

Jacques Sineriz

Быстрый и грязный javascript

var TAB_LEN = 4;
// The function
function tabs2Spaces (str){
	return str.replace(/^([\ \t]+)/, (m, p)=>{
		return p.split('').reduce((p, q) => { 
			return q==' '?p+q : p+' '.repeat(TAB_LEN - p.length % TAB_LEN); 
		}, '');
	});
}
// The test
function showSpaces(str){
	return str.replace(/^([\ \t]+)/, (m, p)=>{
		return p.replace(/\ /g, '[ ]').replace(/\t/g, '[tab]');
	});	
}
var tests = ['  	Hello, world!', '   		 	Hello, World!'];
tests.forEach( s=> { 
	console.log('Before:\t' + showSpaces(s));
	console.log('After:\t' + showSpaces(tabs2Spaces(s)));
});
/* OUTPUT
Before: [ ][ ][tab]Hello, world!
After:  [ ][ ][ ][ ]Hello, world!
Before: [ ][ ][ ][tab][tab][ ][tab]Hello, World!
After:  [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]Hello, World!
*/


Рейтинг:
2

Maarten1977

Код:

static string ReplaceTabWithSpaces(string text)
{
	var spaceCount = 0;
	var builder = new StringBuilder();
	for (var pos = 0; pos < text.Length; pos++)
	{
		if (text[pos] == ' ')
		{
			spaceCount++;
			if (spaceCount == 4)
			{
				spaceCount = 0;
				builder.Append("    ");
			}
		}
		else if (text[pos] == '\t')
		{
			builder.Append("    ");
			spaceCount = 0;
		}
		else
		{
			if (spaceCount > 0)
			{
				builder.Append(string.Empty.PadLeft(spaceCount));
				spaceCount = 0;
			}
			builder.Append(text[pos]);
		}
	}
	if (spaceCount > 0)
	{
		builder.Append(string.Empty.PadLeft(spaceCount));
	}
	return builder.ToString();
}

static string Decode(string text)
{
	return text.Replace("[ ]", " ").Replace("[tab]", "\t");
}

static string Encode(string text)
{
	return text.Replace(" ", "[ ]").Replace("\t", "[tab]");
}

static void Main(string[] args)
{
	var text = "[ ][ ][tab]Hello, world!";
	Console.WriteLine("Input : {0}", text);
	Console.WriteLine("Output: {0}", Encode(ReplaceTabWithSpaces(Decode(text))));

	text = "[ ][ ][ ][tab][tab][ ][tab]Hello, world!";
	Console.WriteLine("Input : {0}", text);
	Console.WriteLine("Output: {0}", Encode(ReplaceTabWithSpaces(Decode(text))));

	Console.ReadLine();
}


Выход:

Input : [ ][ ][tab]Hello, world!
Output: [ ][ ][ ][ ]Hello,[ ]world!
Input : [ ][ ][ ][tab][tab][ ][tab]Hello, world!
Output: [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]Hello,[ ]world!


Рейтинг:
2

Graeme_Grant

Я включил 2 версии: ExpandSimple для традиционных; & ExpandCompact для чего-то немного другого.

Код:

class Program
{
    static void Main(string[] args)
    {
        int tabstopSize = 4;

        string Test1 = "  \tHello, World!";
        string validate1 = "    Hello, World!";

        string Test2 = "   \t\t \tHello, world!";

        string result1a = Test1.ExpandSimple(tabstopSize);

        Console.WriteLine($"Simple 1       Before : {Test1.ShowSpacing()}");
        Console.WriteLine($"                After : {result1a.ShowSpacing()}");
        Console.WriteLine($"              Passed? : {result1a.Equals(validate1)}");
        Console.WriteLine("");

        string result1b = Test1.ExpandCompact(tabstopSize);

        Console.WriteLine($"Compact 1      Before : {Test1.ShowSpacing()}");
        Console.WriteLine($"                After : {result1b.ShowSpacing()}");
        Console.WriteLine($"              Passed? : {result1b.Equals(validate1)}");
        Console.WriteLine("");
        Console.WriteLine($"Simple 1 = Compact 1? : {result1a.Equals(result1b)}");
        Console.WriteLine("");

        string result2a = Test2.ExpandSimple(tabstopSize);

        Console.WriteLine($"Simple 2       Before : {Test2.ShowSpacing()}");
        Console.WriteLine($"                After : {result2a.ShowSpacing()}");
        Console.WriteLine("");

        string result2b = Test2.ExpandCompact(tabstopSize);

        Console.WriteLine($"Compact 2      Before : {Test2.ShowSpacing()}");
        Console.WriteLine($"                After : {result2b.ShowSpacing()}");
        Console.WriteLine("");
        Console.WriteLine($"Simple 2 = Compact 2? : {result2a.Equals(result2b)}");
        Console.WriteLine("");

        Console.WriteLine("-- Press any key to exit --");
        Console.ReadKey();
    }
}

static class Extensions
{
    public static string ExpandSimple(this string input, int tabstopSize)
    {
        int count = 0, pos = 0, inputLength = input.Length;
        var chars = input.ToCharArray();
        var output = new Stack<char>();

        while (pos < inputLength)
        {
            if (chars[pos] == ' ')
            {
                output.Push(chars[pos]);
                count++;
            }
            else if (chars[pos] == '\t')
            {
                for (int i = 0; i < tabstopSize - count; i++)
                    output.Push(' ');
                count = 0;
            }
            else
            {
                break;
            }
            pos++;
        }
        return (new StringBuilder()).Append(new string(output.Select(x => x).ToArray())).Append(new string(chars.Skip(pos).Take(inputLength - pos).ToArray())).ToString();
    }

    public static string ExpandCompact(this string input, int tabstopSize)
    {
        int index = 0;
        return string.Join(string.Empty, input.ToCharArray().Select((x) => x.Equals('\t') ? x.ConvertTabChar(ref index, tabstopSize) : x.ConvertNormChar(ref index)).ToArray());
    }

    public static string ConvertNormChar(this char c, ref int count)
    {
        count++;
        return new string(new char[] { c });
    }

    public static string ConvertTabChar(this char c, ref int count, int tabstopSize)
    {
        int pad = tabstopSize - count % tabstopSize;
        count += pad;
        return new string(Enumerable.Repeat(' ', pad).ToArray());
    }

    public static string ShowSpacing(this string input)
    {
        int pos = 0, inputLength = input.Length;
        var chars = input.ToCharArray();
        var sb = new StringBuilder();
        while (pos < inputLength)
        {
            if (chars[pos] == ' ')
            {
                sb.Append("[ ]");
            }
            else if (chars[pos] == '\t')
            {
                sb.Append(@"[tab]");
            }
            else
            {
                sb.Append(new string(chars.Skip(pos).Take(inputLength - pos).ToArray()));
                break;
            }
            pos++;
        }
        return sb.ToString();
    }
}


Выход:

Simple 1       Before : [ ][ ][tab]Hello, World!
                After : [ ][ ][ ][ ]Hello, World!
              Passed? : True

Compact 1      Before : [ ][ ][tab]Hello, World!
                After : [ ][ ][ ][ ]Hello, World!
              Passed? : True

Simple 1 = Compact 1? : True

Simple 2       Before : [ ][ ][ ][tab][tab][ ][tab]Hello, world!
                After : [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]Hello, world!

Compact 2      Before : [ ][ ][ ][tab][tab][ ][tab]Hello, world!
                After : [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]Hello, world!

Simple 2 = Compact 2? : True

-- Press any key to exit --


Рейтинг:
2

Kornfeld Eliyahu Peter

body {
  tab-size: 4;
}


Patrice T

Боюсь, это не так просто.

Kornfeld Eliyahu Peter

А CSS-это не язык программирования...
Я попытался пошутить в 01: 30 (ночь), но это было так же плохо, как и мое настроение :-)

Patrice T

:-)

Рейтинг:
132

Peter Leow

Это весело. Должен поддерживать и поддерживать его.
Предположим, что "каждая отдельная вкладка заменяется двумя пробелами". Снова быстрый разговор на Python.

"""
tabskiller.py
by Peter Leow the tabs assassin

"""

import re

def convertTabs2Spaces(m):
    # return 2 spaces to replace the spotted tab
    return " "*2

def main():
    # [ ][ ][tab]Hello, world!
    originalSentence = '  	Hello, world!'
    print('Testing 1,2,3...')
    print('Before:')
    print(originalSentence)
    print('After:')
    
    # tab in regex
    patternTab=r'\t'

    convertedSentence = re.sub(patternTab, convertTabs2Spaces, originalSentence)
    print(convertedSentence)

    print('UAT! Use Ctrl+Tab to enter a tab in the IDLE shell. Hit Enter-only to end. Enjoy...')

    while True:
        yourSentence = input('Input a sentence mixed with tabs and spaces:\n')
        if yourSentence == '':
            break
        convertedSentence = re.sub(patternTab, convertTabs2Spaces, yourSentence)
        print(convertedSentence)
  
main()

Выход:
Testing 1,2,3...
Before:
  	    Hello, world!
After:
    Hello, world!
UAT! Use Ctrl+Tab to enter a tab. Hit Enter-only to end. Enjoy...
Input a sentence mixed with tabs and spaces:
			                Hello, world!
          Hello, world!
Input a sentence mixed with tabs and spaces:

Запустите его на локальном холостом ходу, а не на тех онлайн-версиях.
Если я найду время, может быть, придумаю еще один, используя другие языки. Но ничего не обещаю.
++++++++++++++++++++++++++++++++++++++
Как и было обещано, вот и версия C# :
/* 
 * TabsKiller.cs
 * by Peter Leow the tabs assassin
 */

using System;
using System.Text;

class TabsKiller
{
    static void Main(string[] args)
    {
        Console.WriteLine("Testing 1,2,3...");
        Console.WriteLine("Before");
        // [ ][ ][tab]Hello, world!
        string originalSentence = "  	Hello, world!";
        Console.WriteLine(originalSentence);

        Console.WriteLine("After");
        string convertedSentence = convertTabs2Spaces(originalSentence);
        Console.WriteLine(convertedSentence);

        Console.WriteLine("UAT! Hit Enter-only to end. Enjoy...");
        while (true)
        {
            Console.WriteLine("Input a sentence mixed with tabs and spaces:");
            string yourSentence = Console.ReadLine();
            if (yourSentence == string.Empty)
            {
                break;
            }
            Console.WriteLine(convertTabs2Spaces(yourSentence));
        }
    }

    static string convertTabs2Spaces(string sentence)
    {
        StringBuilder sb = new StringBuilder(sentence);
        // replace each tab with 2 spaces
        sb.Replace("\t", "  ");
        return sb.ToString();
    }
}


Рейтинг:
113

Jochen Arndt

Время для старой доброй равнины с:

/* Replace tabs with spaces */
char *untab(int tabwidth, const char *src)
{
    int i, spaces;
    int pos = 0;
    int charpos = 0;
    char *dst;

    /* Allocate enough memory to untab a string containing only tabs */
    dst = (char *)malloc(tabwidth * strlen(src) + 1);
    while (*src)
    {
        switch (*src)
        {
        case '\t' :
            spaces = tabwidth - (linepos % tabwidth);
            for (i = 0; i < spaces; i++)
                dst[pos++] = ' ';
            charpos += spaces;
            break;
        case '\n' :
            charpos = -1;
        default :
            dst[pos++] = *src;
            ++charpos;
        }
        ++src;
    }
    dst[pos] = '\0';
    return dst;
}

ввод-вывод:
[ ][ ][tab]Hello,[ ]world!
[ ][ ][ ][ ]Hello,[ ]world!
    Hello, world!
[ ][ ][ ][tab][tab][ ][tab]Hello,[ ]world!
[ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]Hello,[ ]world!
            Hello, world!


Когда имеется только один выходной канал (например, файл ) , untab() функция может быть изменена для обработки только отдельных символов и печати выходных данных непосредственно при создании charpos статический. Это позволит избежать выделения памяти для каждой строки. Но я выбрал вышеприведенное решение для поддержки форматированного вывода и как оно есть.


Для тех ,кто хотел бы воспроизвести его (может быть расширен для поддержки чтения из файла, stdin, каналов и вывода в файл):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Insert untab() from above here */

void print(const char *s)
{
    int newline = 0;
    while (*s)
    {
        switch (*s)
        {
            case '\t' : printf("[tab]"); break;
            case ' '  : printf("[ ]"); break;
            case '\n' : newline = 1;
            default   : putchar(*s);
        }
        ++s;
    }
    /* Using puts("") here to print a system dependant newline */
    if (!newline)
        puts("");
}

void test(int tabwidth)
{
    char *untabbed;
    const char *test1 = "  \tHello, world!";
    const char *test2 = "   \t\t \tHello, world!";

    untabbed = untab(tabwidth, test1);
    print(test1);
    print(untabbed);
    printf("%s", untabbed);
    puts("");
    free(untabbed);

    untabbed = untab(tabwidth, test2);
    print(test2);
    print(untabbed);
    printf("%s", untabbed);
    puts("");
    free(untabbed);
}

int main()
{
    test(4);
    return 0;
}


Рейтинг:
1

mfp labs

Просто хотел показать, что - хотя многие люди говорят, что регулярное выражение такое классное и элегантное (???) - регулярное выражение ооочень медленное :-)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace CodingFromTheField.NukeStrings
{
    class Program
    {        
        static void Main(string[] args)
        {
            string input = "   \t\t \tHello, world!";

            Nuker nu = new Nuker();

            nu.NukeThis(input, "\t", "    ");

            input.WaitForUser();
        }
    }

    public class Nuker
    {
        public string OrgString { get; set; }

        protected Stopwatch Timer { get; set; }

        protected long RT1 { get; set; }

        protected long RT2 { get; set; }

        protected const int Iterations = 10000;

        protected Dictionary<string, string> Escaper = new Dictionary<string, string> { { " ", "[ ]" }, { "\t", "[tab]" } };

        public Nuker() { }

        public string NukeThis(string input, string replace, string replacement)
        {
            string ret = input;

            this.OrgString = ret;

            ret = Measure1(input, replace, replacement);

            Console.WriteLine("Measure1: \"{0}\".Replace(\"{1}\", \"{2}\") -> {3} ms ({4} iterations)",
                              input.Escape(Escaper), replace.Escape(Escaper), replacement.Escape(Escaper), this.RT1, Iterations);

            Console.WriteLine("\"{0}\" nuked to \"{1}\"", input.Escape(Escaper), ret.Escape(Escaper));

            Measure2(input, replace, replacement);
            
            Console.WriteLine("Measure1: Regex.Replace(\"{0}\", \"{1}\", \"{2}\") -> {3} ms ({4} iterations)",
                              input.Escape(Escaper), replace.Escape(Escaper), replacement.Escape(Escaper), this.RT2, Iterations);

            Console.WriteLine("\"{0}\" nuked to \"{1}\"", input.Escape(Escaper), ret.Escape(Escaper));

            long fact = this.RT2 / this.RT1;

            Console.WriteLine("String.Replace is ~{0} times {1} than Regex.Replace!", fact, (fact > 1) ? "faster" : "slower" );

            return ret;
        }

        protected string Measure1(string input, string replace, string replacement)
        {
            string ret = input;

            StartTimer();

            for (int cnt = 0; cnt <= Iterations; cnt++)
            { ret = input.Replace(replace, replacement); }

            this.RT1 = StopTimer();

            return ret;
        }

        protected string Measure2(string input, string replace, string replacement)
        {
            string ret = input;

            StartTimer();

            replace = Regex.Escape(replace);

            for (int cnt = 0; cnt <= Iterations; cnt++)
            { ret = Regex.Replace(input, replace + "[0-9]", replacement, RegexOptions.IgnoreCase); ; }

            this.RT2 = StopTimer();

            return ret;
        }

        protected void StartTimer()
        {
            if (this.Timer == null)
            { this.Timer = new Stopwatch(); }

            else
            { this.Timer.Reset(); }

            this.Timer.Start();
        }

        protected long StopTimer()
        {
            long ret = 0;

            if (this.Timer.IsRunning)
            {
                ret = this.Timer.ElapsedMilliseconds;

                this.Timer.Reset();
            }

            return ret;
        }
    }

    public static class ExtensionMethods
    {
        public static void WaitForUser(this object value)
        { Console.WriteLine("\r\npress any key to exit"); Console.ReadKey(); }

        public static string Escape(this string value, Dictionary<string, string> escaper)
        {
            string ret = value;

            foreach (KeyValuePair<string, string> kvp in escaper)
            { ret = ret.Replace(kvp.Key, kvp.Value); }

            return ret;
        }
    }
}


ScottM1

Я думаю, что вы, возможно, слишком много читали об этом.

mfp labs

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

Кстати. - Выход
Measure1: "[ ][ ][ ][разделе][разделе][ ][вкладка]Здравствуйте,[ ]мир!".Заменить("[вкладка]", "[ ][ ][ ][ ]") -&ГТ; 2 мс (10000 итераций)
"[ ][ ][ ][разделе][разделе][ ][вкладка]Здравствуйте,[ ]мир!" сбросили атомную бомбу на "[ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]Здравствуйте,[ ]мира!"

Measure1: Регулярное Выражение.Заменить("[ ][ ][ ][разделе][разделе][ ][вкладка]Здравствуйте,[ ]мир!", "[вкладка]", "[ ][ ][ ][ ]") -&и GT; 16 мс (10000 итераций)
"[ ][ ][ ][разделе][разделе][ ][вкладка]Здравствуйте,[ ]мир!" сбросили атомную бомбу на "[ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]Здравствуйте,[ ]мира!"

Строка.Replace примерно в 8 раз быстрее, чем Regex.Replace!

нажмите любую клавишу для выхода

Всего наилучшего
Майкл

Рейтинг:
1

F. Xaver

почему бы и нет VB.net один?

здесь:

Module Module1

     Sub Main()
          Dim TestStrings As New List(Of String)
          TestStrings.Add("[ ][ ][tab]Hello, world!")
          TestStrings.Add("[ ][ ][ ][tab][tab][ ][tab]Hello, world!")

          Const TabStopAt As Integer = 4

          Console.WriteLine("Running Tap Replacement Tests...")
          Console.WriteLine()

          RunTests(TestStrings, TabStopAt)

          Console.WriteLine()
          Console.WriteLine("Press any Key to end this App")
          Console.ReadKey()
     End Sub


     Sub RunTests(Tests As List(Of String), TapStop As Integer)
          For Each Test As String In Tests
               Console.WriteLine("Performing new Test!")
               Console.WriteLine("#####################")
               Console.WriteLine("Original String: {0}", Test)
               Test = RemoveDisplayStrings(Test)
               Console.WriteLine("Cleared String : {0}", Test)
               Test = ReplaceTabs(Test, TapStop)
               Console.WriteLine("Replaced String: {0}", Test)
               Test = AddDisplayStrings(Test)
               Console.WriteLine("Debug String   : {0}", Test)
               Console.WriteLine("#####################")
               Console.WriteLine()
          Next
     End Sub


     Function ReplaceTabs(Original As String, TabStop As Integer) As String
          Dim this As New List(Of Char)
          For Each c As Char In Original.ToCharArray
               If c = ControlChars.Tab Then
                    this.AddRange(New String(" "c, GetDiffToTabMarker(this.Count, TabStop)).ToCharArray)
               Else
                    this.Add(c)
               End If
          Next

          Return New String(this.ToArray)
     End Function


     Function GetDiffToTabMarker(Length As Integer, TabStop As Integer) As Integer
          Dim this As Integer = Length Mod TabStop
          If this > 0 Then this = TabStop - this
          If this = 0 Then this = TabStop
          Return this
     End Function

     Function RemoveDisplayStrings(Original As String) As String
          Return Original.Replace("[ ]", " ").Replace("[tab]", ControlChars.Tab)
     End Function

     Function AddDisplayStrings(Original As String) As String
          Return Original.Replace(" ", "[ ]").Replace(ControlChars.Tab, "[tab]")
     End Function
End Module



Выход:
Running Tap Replacement Tests...

Performing new Test!
#####################
Original String: [ ][ ][tab]Hello, world!
Cleared String :   	Hello, world!
Replaced String:     Hello, world!
Debug String   : [ ][ ][ ][ ]Hello,[ ]world!
#####################

Performing new Test!
#####################
Original String: [ ][ ][ ][tab][tab][ ][tab]Hello, world!
Cleared String :    		 	Hello, world!
Replaced String:             Hello, world!
Debug String   : [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]Hello,[ ]world!
#####################


Press any Key to end this App


Рейтинг:
1

Jacek M Glen

using System.Text;
using NUnit.Framework;
namespace Code_Project_Challenge
{
    class TabConverter
    {
        static int tabLength = 4;
        public string Convert(string str)
        {
            var sb = new StringBuilder(str.Length);
            int charCount = 0, spacesToAdd;

            foreach (var c in str)
            {
                if (c == '\t')
                {
                    spacesToAdd = tabLength - (charCount % tabLength);
                    sb.Append(' ', spacesToAdd);
                    charCount += spacesToAdd;
                }
                else
                {
                    sb.Append(c);
                    charCount++;
                }
            }

            return sb.ToString();
        }
    }

    [TestFixture]
    public class TabConverterTest
    {
        [Test]
        [TestCase("  \tHello, world!", "    Hello, world!")]
        [TestCase("   \t\t \tHello, world!", "            Hello, world!")]
        public void Returns(string inStr, string expected)
        {
            var sut = new TabConverter();
            var result = sut.Convert(inStr);
            Assert.AreEqual(expected, result);
        }
    }
}


Рейтинг:
1

CPallini

Lua:

local function tab2blank(s)
  local n=1
  return s:gsub('(.-)\t', function(s) n = n + #s; b = 4 - (n-1) % 4; n = n + b; return s.. string.rep(' ', b) end)
end


Тестовая программа:
local function format(s)
  return s:gsub("([ \t])", function (p) return p == ' ' and '[ ]' or '[tab]' end )
end

local t = { "  \tHello, world!", "   \t\t \tHello, world!" }

local function tab2blank(s)
  local n=1
  return s:gsub('(.-)\t', function(s) n = n + #s; b = 4 - (n-1) % 4; n = n + b; return s.. string.rep(' ', b) end)
end

for k,s in ipairs(t) do
  print("item " .. k .. ":")
  print(format(s) .. " -> " .. format(tab2blank(s)))
end

Выход:
item 1:
[ ][ ][tab]Hello,[ ]world! -> [ ][ ][ ][ ]Hello,[ ]world!
item 2:
[ ][ ][ ][tab][tab][ ][tab]Hello,[ ]world! -> [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]Hello,[ ]world!


Рейтинг:
1

Fraser Duthie

В javascript это можно сделать с помощью одного составного оператора. Используя функцию indexOf, мы можем определить положение символа табуляции по этому выражению

tabPosition=theText.indexOf("\t")
что дает нам нулевую индексированную позицию или -1, если нет оставшихся вкладок.

Количество пробелов, которые нам нужно добавить, будет не более четырех, но мы должны обрезать его на остаток tabPosition, деленный на 4 (т. е. tabPosition%4), так что общее количество символов после замены будет точно кратно 4 символам. т. е. мы должны заменить символ tab этим строковым выражением:
("    ").substr(0,4-tabPosition%4)

В тексте может быть более одной вкладки, поэтому мы должны повторять замену до тех пор, пока tabPosition не будет равен -1. Сложение всего этого вместе дает:

while((tabPosition=theText.indexOf("\t"))!=-1)theText=theText.replace("\t",("    ").substr(0,4-tabPosition%4));


Эта единственная строка-Все,что нам нужно, чтобы превратить текст в версию с вкладками по отдельным пробелам. Очевидно, что это более полезно как функция, но почему бы не добавить немного больше функциональности, чтобы вкладки могли быть 2, 3, 4 ....12 позиции персонажей разделены? Нам просто нужно заменить число 4 в нашем операторе coumpund переменной и сделать так, чтобы строка пробела содержала больше пробелов.
function tabs2Spaces(theText,tabSpacing)
{
	while((tabPosition=theText.indexOf("\t"))!=-1)theText=theText.replace("\t",("            ").substr(0,tabSpacing-tabPosition%tabSpacing));
	return theText;
}

// show how the function can align tab spaces irrespective of no of characters before:
document.writeln ("Using tab positions 4 characters apart:")
document.writeln(tabs2Spaces("\tHello World",4));
document.writeln(tabs2Spaces("  \tHello World",4));
document.writeln(tabs2Spaces("  \tHello World",4));
document.writeln(tabs2Spaces("   \tHello World",4));
document.writeln(tabs2Spaces("    \tHello World",4));
document.writeln(tabs2Spaces("     \tHello World",4));
document.writeln(tabs2Spaces("      \tHello World",4));
document.writeln(tabs2Spaces("       \tHello World",4));
document.writeln ("Using tab positions 6 characters apart:")
document.writeln(tabs2Spaces("\tHello World",6));
document.writeln(tabs2Spaces("  \tHello World",6));
document.writeln(tabs2Spaces("  \tHello World",6));
document.writeln(tabs2Spaces("   \tHello World",6));
document.writeln(tabs2Spaces("    \tHello World",6));
document.writeln(tabs2Spaces("     \tHello World",6));
document.writeln(tabs2Spaces("      \tHello World",6));
document.writeln(tabs2Spaces("       \tHello World",6));
document.writeln ("Using tab positions 9 characters apart:")
document.writeln(tabs2Spaces("\tHello World",9));
document.writeln(tabs2Spaces("  \tHello World",9));
document.writeln(tabs2Spaces("  \tHello World",9));
document.writeln(tabs2Spaces("   \tHello World",9));
document.writeln(tabs2Spaces("    \tHello World",9));
document.writeln(tabs2Spaces("     \tHello World",9));
document.writeln(tabs2Spaces("      \tHello World",9));
document.writeln(tabs2Spaces("       \tHello World",9));


.... который выводит этот текст ...
Using tab positions 4 characters apart:
    Hello World
    Hello World
    Hello World
    Hello World
        Hello World
        Hello World
        Hello World
        Hello World
Using tab positions 6 characters apart:
      Hello World
      Hello World
      Hello World
      Hello World
      Hello World
      Hello World
            Hello World
            Hello World
Using tab positions 9 characters apart:
         Hello World
         Hello World
         Hello World
         Hello World
         Hello World
         Hello World
         Hello World
         Hello World


Рейтинг:
1

Jacek M Glen

LINQy-версия моего предыдущего решения. Он правильно работает для вкладок, размещенных в любом месте текста, всегда выравниваясь до %4 (или %tabLength).

using System.Linq;
using NUnit.Framework;
namespace Code_Project_Challenge
{
    class TabConverter
    {
        static int tabLength = 4;

        public string Convert(string str)
        {
            int charCount = 0, spacesToAdd;

            return string.Join("", str.Select(ch => {
                if (ch == '\t')
                {
                    spacesToAdd = tabLength - (charCount % tabLength);
                    charCount += spacesToAdd;
                    return new string(' ', spacesToAdd);
                }
                else
                {
                    charCount++;
                    return ch.ToString();
                }
            }));
        }
    }

    [TestFixture]
    public class TabConverterTest
    {
        [Test]
        [TestCase("  \tHello, world!", "    Hello, world!")]
        [TestCase("   \t\t \tHello, world!", "            Hello, world!")]
        [TestCase("   \ta     \t \tHello\t, world!", "    a           Hello   , world!")]
        public void Returns(string inStr, string expected)
        {
            var sut = new TabConverter();
            var result = sut.Convert(inStr);
            Assert.AreEqual(expected, result);
        }
    }
}


Graeme_Grant

Выглядит ужасно близко к тому, что я имел выше с ExpandCompact...

Jacek M Glen

О, я пропустил ваше решение, прежде чем опубликовать свое.
Действительно, подход очень похож. Похоже великие умы думают одинаково ;)

losvce

Эта версия LINQy намного, намного лучше, чем то, что я пробовал в своем решении. Я просто не мог заставить его работать за то время, что потратил на него. Спасибо за перспективу!

Рейтинг:
0

Thomas Daniels

Brainfuck


Что ж, это было весело :)
>,[>+++++++++<[>->+<<-]>[>-------------------------------->-------------------------------->]<++++++++++++++++++++++++++++++++[.--------------------------------]<++++++++++++++++++++++++++++++++.>>>,]

Чтобы запустить это, вставьте код в этот онлайн переводчик[^], заполните свой ввод в поле "ввод" и нажмите кнопку "Выполнить".

Так что же на самом деле здесь происходит? Вот объясненный код (в то время как Brainfuck игнорирует символы, которые он не знает, приведенный ниже код не может быть запущен, потому что комментарий содержит некоторые символы, которые действительны в Brainfuck).
>  # Jump a cell ahead. We'll need the first cell later.
,  # Find a char in the input.
[  # If there is no input, jump past the matching ]. Here that ends the program.

  >  # Jump another cell ahead.
  +++++++++  # Put the value 9 in this cell.

  <  # Jump one cell back (to our input cell).
  [>->+<<-]  # While this cell is not 0, do these things: a) decrement the value at the next cell. b) increment the value two cells ahead. c) decrement the value of our input cell

  # Now the cell that originally contained our input is 0, the cell ahead of that one is non-zero if the input is no tab, zero if it is a tab (I'll call this the "signal cell"), and the cell ahead of THAT one is a copy of our original input.

  >  # Jump to the signal cell.
  [  # If the cell is zero, jump to the matching ], otherwise continue.
    >--------------------------------  # Jump to our input copy and decrease the value by 32.
    >--------------------------------  # Jump another cell ahead and do the same. (This cell starts at 0 and won't end up at -32 but 224 because of underflow. It doesn't matter though.
    >  # Jump to the next cell, to be sure that this one is zero and we are not stuck in a loop.
  ]  # If the current cell value is zero (which it is!), just continue the program (otherwise go back to the matching [).

  <  # Jump back a cell. If our input was a tab, this new cell will be the cell we skipped in the beginning. If it wasn't a tab, it will be our "224 cell".
  ++++++++++++++++++++++++++++++++  # Increase by 32. In case of a tab, this will be 32, otherwise 0.
  [.--------------------------------]  # If the value is not 0 (then it must be a space), print it and make sure it only gets called once. This makes sure that a tab gets replaced with TWO spaces as the challenge requires.

  <  # Jump back a cell. If our input was a tab this will be 0, otherwise the original char minus 32.
  ++++++++++++++++++++++++++++++++  # Increase by 32.
  .  # Print.

>>>  # Jump three cells ahead, so we don't have to worry about our past cells. Here we also keep our "spare cell" in mind like in the beginning of the program.
,  # Look for a char in the input.
]  # Is it 0? No input anymore and close the program. Not 0? Go back to the first [.


Chris Maunder

-2 балла за использование самого тупого языка на свете. +4 балла за боль.

Matthew Dennis

на самом деле, вероятно, не в топ-10 самых тупых языков. Попробовать тоже https://en.wikipedia.org/wiki/Malbolge. Я даже не собираюсь пытаться.

Рейтинг:
0

losvce

Может быть, я воспринимал все слишком буквально.

using System;
using System.Collections.Generic;
using System.Linq;

namespace Test
{
    public class TabConversion
    {              
        public static void Main(string[] args)
        {
            string literalTest1 = "[ ][ ][tab]Hello, world!";
            string literalTest2 = "[ ][ ][ ][tab][tab][ ][tab]Hello, world!";

            DoTests(new string[] { literalTest1, literalTest2 }, "[tab]", "[ ][ ]");
            DoTests(new string[] { 
                literalTest1.Replace("[tab]", "\t").Replace("[ ]"," "), 
                literalTest2.Replace("[tab]", "\t").Replace("[ ]"," ") }, 
                "\t", "  ");
        }

        // This is probably the fastest way
        public static string ReplaceTabs(string text, string tabText, string spaceText)
        {
            return text.Replace(tabText, spaceText);
        }

        // This is a bad way, but hey, it works
        public static string ReplaceTabsBySplitting(string text, string tabText, string spaceText)
        {
            var splits = text.Split(new string[] { tabText }, StringSplitOptions.None);
            if (splits.Length > 1)
            {
                return string.Join(spaceText, splits);
            }
            else
            {
                return text;
            }
        }

        // What is this I don't even
        public static string ReplaceTabsByLinq(string text, string tabText, string spaceText)
        {
            List<string> t = new List<string>();
            text.Split(new string[] { tabText }, StringSplitOptions.None).ToList().ForEach(s => { t.Add(s); t.Add(tabText); });
            string result = string.Join("", t.Select<string, string="">(s => s == tabText ? spaceText : s).ToArray<string>().Reverse().Skip(1).Reverse());
            return result;
        }

        // Felt bad about replacing the tabs.  Tab lives matter!
        public static string UnreplaceTabs(string text, string tabText, string spaceText)
        {
            return text.Replace(spaceText, tabText);
        }

        // DRY
        public static void DoTests(string[] tests, string tabText, string spaceText)
        {
            foreach (string test in tests)
            {
                Console.WriteLine("-----------------------------");
                Console.WriteLine("Original\t\"" + test + "\"");
                Console.WriteLine();
                Console.WriteLine("string.Replace\t\"" + ReplaceTabs(test, tabText, spaceText) + "\"");
                Console.WriteLine("string.Split\t\"" + ReplaceTabsBySplitting(test, tabText, spaceText) + "\"");
                Console.WriteLine("Using LINQ\t\"" + ReplaceTabsByLinq(test, tabText, spaceText) + "\"");
                Console.WriteLine("Space->Tab\t\"" + UnreplaceTabs(test, tabText, spaceText) + "\"");
                Console.WriteLine();
            }
        }
    }
}


Вероятно, можно было бы свести метод LINQ к одной строке, но сейчас у меня нет времени.


Рейтинг:
0

H2O-au

Я думал, что попробую это сделать, но, увы, мое решение кажется слишком разумным для этой задачи... :D

Использование перечисляемых объектов C# и yield...

public static partial class Extensions
{
    public static string ToTabified(this string input, int markerSpacing = 4)
    {
        return new string(tabEnumerable(input, markerSpacing).ToArray());
    }

    private static IEnumerable<char> tabEnumerable(
        IEnumerable<char> input,
        int markerSpacing)
    {
        var n = 0;
        using (var e = input.GetEnumerator())
            while (e.MoveNext())
            {
                if (e.Current == '\t')
                {
                    // at least one
                    yield return ' ';
                    n++;

                    // then fill to next marker
                    while (n % markerSpacing != 0)
                    {
                        yield return ' ';
                        n++;
                    }
                }
                else
                {
                    yield return e.Current;
                    n++;
                }
            }
    }
}


Рейтинг:
0

lbesteban

With 3 lines of code and 25 bytes 

******************** File a.lex ********************
%{
/* Thanks to CPallini for pointing out a bug
   my vote for a T-Shirt is for him  */
%}
%%
\t printf(" ");
%%
******************** end of a.lex ********************

Compile & execute
flex a.lex
gcc lex.yy.c -lfl
./a.out < samples

where samples is a file containing all sorts of test strings with tabs and or spaces

Make it more fancy by adding new pattern recognition
A special return code like on last like int main(){return(yylex());}
.....
and so on., kind of freak though, had'nt used lex since years


CPallini

синтаксис не на 100% корректен (комментарии должны быть написаны %{ ... %})
Однако главная проблема вашего кода заключается в том, что он заменяет каждый экземпляр вкладки с четырьмя пробелами. Это не запрошенное поведение (насколько я понимаю).

lbesteban

Да, вы правы, я ошибся, прочитав его
"Учитывая текстовую строку, преобразуйте табуляции в пробелы. "

Правильное решение-печатать только один пробел. что сокращает 3 байта.

Мой плохой, слишком взволнованный, чтобы увидеть, что на самом деле то, что я не использовал с тех пор, как покинул университет в конце 90-х, может быть так быстро решить эту проблему.

******************** Подать.Лекс ********************
%%
\т е(" ");
%%
******************** окончание.Лекс ********************

И формат правильный, комментариев к этому нет

Да, в flex вы можете иметь комментарии, но парсер определяется как

[блок определений]
%%
[блок распознавания токенов]
%%
[логика программы]

Комментарии, как и в любом языке Си, заключены между строками кода % {[...... ]%}

CPallini

Действительно, Лекс и бизон были (есть) очаровательны.
:-)

Рейтинг:
0

MikeD 2

он не получит футболку, но не может обойтись без решения VB6 :-)

разочарованный я не получил Гото в ответ

Private Const TabStop = 4
Private Function TabExpand(strInput As String) As String
Dim i As Integer, col As Integer, tabFound As Integer, StartPos As Integer, Padlen As Integer
Dim strOutput As String
    StartPos = 1
    tabFound = InStr(StartPos, strInput, vbTab)
    If tabFound = 0 Then
        TabExpand = strInput
        Exit Function
    End If
    Do While tabFound > 0
        strOutput = strOutput & Mid(strInput, StartPos, tabFound - StartPos)
        Padlen = TabStop - (Len(strOutput) Mod TabStop)
        strOutput = strOutput & Space(Padlen)
        StartPos = tabFound + 1
        tabFound = InStr(StartPos, strInput, vbTab)
    Loop
    If StartPos < Len(strInput) Then
        strOutput = strOutput & Mid(strInput, StartPos)
    End If
    TabExpand = strOutput
End Function


Рейтинг:
0

AVNTizzy

QBASIC baby! Мой отец был бы так горд. Ха.

DIM TABBYTABS$
DIM SPACYMCSPACE$
TABBYTABS$ = "   " + CHR$(9) + CHR$(9) + " " + CHR$(9) + "Hello World!"
FOR I = 1 TO LEN(TABBYTABS$) STEP 1
    IF ASC(MID$(TABBYTABS$, I, 1)) = 9 THEN
        SPACYMCSPACE$ = SPACYMCSPACE$ + " "
    ELSE
        SPACYMCSPACE$ = SPACYMCSPACE$ + MID$(TABBYTABS$, I, 1)
    END IF
NEXT I
PRINT TABBYTABS$
PRINT SPACYMCSPACE$


Рейтинг:
0

GeeTee86

setlocal enabledelayedexpansion
for /f "tokens=*" %%a in (h:\myFile.txt) делать (
set row=%%a
набор строк=!строки:,= !
Эхо.!подряд!&ГТ;&ГТ;h:\changed.txt
)

поместите текст в myfile.txt
сохраните как xxx. bat и запустите через командную строку windows
он заменяет пробелы табуляциями-потому что в противном случае


Рейтинг:
0

Ramza360

Расширение строки с хорошим черепашьим темпом неизменяемой манипуляции строкой.

public static string RemoveTabs(this string input) {
    if (string.IsNullOrWhiteSpace(input)) {
         return input;
    }

    int idx = 0;

    while (true) {
        if (idx >= input.Length) {
            break;
        }

        if (input[idx] == '\t') {
            input = input.Remove(idx, 1);
            int cur = idx;

            while (cur < idx + 4) {
                input = input.Insert(cur, '[ ]');
                cur++;
            }

            idx += 4;
            continue;
        }

        idx++;
    }

    input = input.Replace("[tab]", "[ ][ ][ ][ ]");
 
    return input;
}


Воспользуйся:
string test = "CONVERT\tTABS\t\t-\tTo SPACES".RemoveTabs();
Console.WriteLine(test);
// Or
test = "CONVERT\tTABS\t\t-\tTo SPACES";
test = test.RemoveTabs();
Console.WriteLine(test);


Пришлось добавить еще одну.. ILE RPG (НЕПРОВЕРЕННАЯ)

D test S 45A   INZ('CONVERT x'05' TABS x'05'- x'05' To SPACES') VARYING
D tester S 45A   INZ('CONVERT [tab] TABS [tab]- [tab] To SPACES') VARYING
test = %ScanRpl(x'05' : '[ ][ ][ ][ ]' : test);
tester = %ScanRpl('[tab]' : '[ ][ ][ ][ ]' : tester);


Рубин

test = "CONVERT [tab] TABS [tab]- [tab] To SPACES"
test = test.gsub("[tab]", "[ ][ ][ ][ ]")