Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.theory > #50308 > unrolled thread
| Started by | olcott <NoOne@NoWhere.com> |
|---|---|
| First post | 2022-05-12 17:51 -0500 |
| Last post | 2022-05-13 14:19 -0500 |
| Articles | 20 on this page of 36 — 7 participants |
Back to article view | Back to comp.theory
Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-12 17:51 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Mr Flibble <flibble@reddwarf.jmc> - 2022-05-12 23:56 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-12 18:09 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Mr Flibble <flibble@reddwarf.jmc> - 2022-05-13 00:22 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-12 18:38 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Mr Flibble <flibble@reddwarf.jmc> - 2022-05-13 00:40 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-12 18:49 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Mr Flibble <flibble@reddwarf.jmc> - 2022-05-13 00:53 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-12 19:12 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Mr Flibble <flibble@reddwarf.jmc> - 2022-05-13 01:58 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-12 20:34 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Mr Flibble <flibble@reddwarf.jmc> - 2022-05-13 08:02 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque tth <tth@none.invalid> - 2022-05-13 09:10 +0200
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-13 10:58 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Mr Flibble <flibble@reddwarf.jmc> - 2022-05-13 17:02 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2022-05-13 12:44 -0700
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Richard Damon <Richard@Damon-Family.org> - 2022-05-12 19:23 -0400
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-12 18:32 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Ben <ben.usenet@bsb.me.uk> - 2022-05-13 01:06 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-12 19:55 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Mr Flibble <flibble@reddwarf.jmc> - 2022-05-13 02:01 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-12 20:36 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Mr Flibble <flibble@reddwarf.jmc> - 2022-05-13 08:04 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-13 11:00 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Mr Flibble <flibble@reddwarf.jmc> - 2022-05-13 17:04 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-13 12:05 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Ben <ben.usenet@bsb.me.uk> - 2022-05-13 02:38 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-12 21:37 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Python <python@example.invalid> - 2022-05-13 04:39 +0200
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Ben <ben.usenet@bsb.me.uk> - 2022-05-13 12:01 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-13 10:41 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Richard Damon <Richard@Damon-Family.org> - 2022-05-13 11:56 -0400
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Ben <ben.usenet@bsb.me.uk> - 2022-05-13 17:35 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-13 12:12 -0500
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque Ben <ben.usenet@bsb.me.uk> - 2022-05-13 20:04 +0100
Re: Implementing a two-way Turing Machine tape as an improvement to std::deque olcott <NoOne@NoWhere.com> - 2022-05-13 14:19 -0500
Page 1 of 2 [1] 2 Next page →
| From | olcott <NoOne@NoWhere.com> |
|---|---|
| Date | 2022-05-12 17:51 -0500 |
| Subject | Implementing a two-way Turing Machine tape as an improvement to std::deque |
| Message-ID | <cNWdnXqV1cXzEuD_nZ2dnUU7_8zNnZ2d@giganews.com> |
C/C++ people please critique this as the basis for an improvement to
std::deque. It seems to have the key functionality of std::deque and
does it much more simply while saving time and space.
https://www.cplusplus.com/reference/deque/deque/
#define tape_element unsigned char
class Tape_Type
{
private:
int Tape_Head = 0; // Can be negative
std::vector<tape_element> Left; // Stores left expansion
std::vector<tape_element> Right; // Stores right expansion
tape_element & operator[](int index);
public:
void move_left(); // Tape_Head--; Left.push_back(0); as needed
void move_right(); // Tape_Head++; Left.push_back(0); as needed
void Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
tape_element Read() { return this->operator[](Tape_Head); };
Tape_Type(){ Right.push_back('_'); } // constructor
void Output();
};
tape_element& Tape_Type::operator[](int index)
{
if (index > 0)
return Right[index];
int Left_Index = ((index * -1) -1);
return Left[Left_Index];
}
void Tape_Type::Output()
{
printf("Tape_Type::Output()\n");
if (Left.size())
{
int Last_One = Left.size() - 1;
for (int N = Last_One; N >= 0; N--)
{
int TH = (N + 1) * -1; // determine Tape_Head from N
printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
}
}
if (Right.size())
for (int N = 0; N < Right.size(); N++)
printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
}
void Tape_Type::move_left()
{
Tape_Head--;
int Left_Index = ((Tape_Head * -1) -1);
if (Left_Index == Left.size())
Left.push_back('_');
}
void Tape_Type::move_right()
{
Tape_Head++;
if (Tape_Head == Right.size())
Right.push_back('_');
}
--
Copyright 2022 Pete Olcott
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
[toc] | [next] | [standalone]
| From | Mr Flibble <flibble@reddwarf.jmc> |
|---|---|
| Date | 2022-05-12 23:56 +0100 |
| Message-ID | <20220512235610.00004914@reddwarf.jmc> |
| In reply to | #50308 |
On Thu, 12 May 2022 17:51:25 -0500
olcott <NoOne@NoWhere.com> wrote:
> C/C++ people please critique this as the basis for an improvement to
> std::deque. It seems to have the key functionality of std::deque and
> does it much more simply while saving time and space.
> https://www.cplusplus.com/reference/deque/deque/
>
> #define tape_element unsigned char
>
> class Tape_Type
> {
> private:
> int Tape_Head = 0; // Can be negative
> std::vector<tape_element> Left; // Stores left expansion
> std::vector<tape_element> Right; // Stores right expansion
> tape_element & operator[](int index);
>
> public:
> void move_left(); // Tape_Head--; Left.push_back(0); as needed
> void move_right(); // Tape_Head++; Left.push_back(0); as needed
> void Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
> tape_element Read() { return this->operator[](Tape_Head); };
> Tape_Type(){ Right.push_back('_'); } // constructor
> void Output();
> };
>
> tape_element& Tape_Type::operator[](int index)
> {
> if (index > 0)
> return Right[index];
> int Left_Index = ((index * -1) -1);
> return Left[Left_Index];
> }
>
> void Tape_Type::Output()
> {
> printf("Tape_Type::Output()\n");
>
> if (Left.size())
> {
> int Last_One = Left.size() - 1;
> for (int N = Last_One; N >= 0; N--)
> {
> int TH = (N + 1) * -1; // determine Tape_Head from N
> printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
> }
> }
> if (Right.size())
> for (int N = 0; N < Right.size(); N++)
> printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
> }
>
> void Tape_Type::move_left()
> {
> Tape_Head--;
> int Left_Index = ((Tape_Head * -1) -1);
> if (Left_Index == Left.size())
> Left.push_back('_');
> }
>
> void Tape_Type::move_right()
> {
> Tape_Head++;
> if (Tape_Head == Right.size())
> Right.push_back('_');
> }
It might be a more appropriate solution than std::deque for your
specific use-case however it is NOT an improvement to std::deque for
the general case -- see my reply in the other thread for why.
/Flibble
[toc] | [prev] | [next] | [standalone]
| From | olcott <NoOne@NoWhere.com> |
|---|---|
| Date | 2022-05-12 18:09 -0500 |
| Message-ID | <Vf2dnR9fAewpDuD_nZ2dnUU7_8xh4p2d@giganews.com> |
| In reply to | #50310 |
On 5/12/2022 5:56 PM, Mr Flibble wrote:
> On Thu, 12 May 2022 17:51:25 -0500
> olcott <NoOne@NoWhere.com> wrote:
>
>> C/C++ people please critique this as the basis for an improvement to
>> std::deque. It seems to have the key functionality of std::deque and
>> does it much more simply while saving time and space.
>> https://www.cplusplus.com/reference/deque/deque/
>>
>> #define tape_element unsigned char
>>
>> class Tape_Type
>> {
>> private:
>> int Tape_Head = 0; // Can be negative
>> std::vector<tape_element> Left; // Stores left expansion
>> std::vector<tape_element> Right; // Stores right expansion
>> tape_element & operator[](int index);
>>
>> public:
>> void move_left(); // Tape_Head--; Left.push_back(0); as needed
>> void move_right(); // Tape_Head++; Left.push_back(0); as needed
>> void Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
>> tape_element Read() { return this->operator[](Tape_Head); };
>> Tape_Type(){ Right.push_back('_'); } // constructor
>> void Output();
>> };
>>
>> tape_element& Tape_Type::operator[](int index)
>> {
>> if (index > 0)
>> return Right[index];
>> int Left_Index = ((index * -1) -1);
>> return Left[Left_Index];
>> }
>>
>> void Tape_Type::Output()
>> {
>> printf("Tape_Type::Output()\n");
>>
>> if (Left.size())
>> {
>> int Last_One = Left.size() - 1;
>> for (int N = Last_One; N >= 0; N--)
>> {
>> int TH = (N + 1) * -1; // determine Tape_Head from N
>> printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
>> }
>> }
>> if (Right.size())
>> for (int N = 0; N < Right.size(); N++)
>> printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
>> }
>>
>> void Tape_Type::move_left()
>> {
>> Tape_Head--;
>> int Left_Index = ((Tape_Head * -1) -1);
>> if (Left_Index == Left.size())
>> Left.push_back('_');
>> }
>>
>> void Tape_Type::move_right()
>> {
>> Tape_Head++;
>> if (Tape_Head == Right.size())
>> Right.push_back('_');
>> }
>
> It might be a more appropriate solution than std::deque for your
> specific use-case however it is NOT an improvement to std::deque for
> the general case -- see my reply in the other thread for why.
>
> /Flibble
>
I didn't see any reason why it would not make a better std::deque.
--
Copyright 2022 Pete Olcott
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
[toc] | [prev] | [next] | [standalone]
| From | Mr Flibble <flibble@reddwarf.jmc> |
|---|---|
| Date | 2022-05-13 00:22 +0100 |
| Message-ID | <20220513002218.00003fa0@reddwarf.jmc> |
| In reply to | #50313 |
On Thu, 12 May 2022 18:09:39 -0500
olcott <NoOne@NoWhere.com> wrote:
> On 5/12/2022 5:56 PM, Mr Flibble wrote:
> > On Thu, 12 May 2022 17:51:25 -0500
> > olcott <NoOne@NoWhere.com> wrote:
> >
> >> C/C++ people please critique this as the basis for an improvement
> >> to std::deque. It seems to have the key functionality of
> >> std::deque and does it much more simply while saving time and
> >> space. https://www.cplusplus.com/reference/deque/deque/
> >>
> >> #define tape_element unsigned char
> >>
> >> class Tape_Type
> >> {
> >> private:
> >> int Tape_Head = 0; // Can be negative
> >> std::vector<tape_element> Left; // Stores left expansion
> >> std::vector<tape_element> Right; // Stores right expansion
> >> tape_element & operator[](int index);
> >>
> >> public:
> >> void move_left(); // Tape_Head--; Left.push_back(0); as
> >> needed void move_right(); // Tape_Head++; Left.push_back(0);
> >> as needed void Write(tape_element Y){ this->operator[](Tape_Head)
> >> = Y; }; tape_element Read() { return
> >> this->operator[](Tape_Head); }; Tape_Type(){ Right.push_back('_');
> >> } // constructor void Output();
> >> };
> >>
> >> tape_element& Tape_Type::operator[](int index)
> >> {
> >> if (index > 0)
> >> return Right[index];
> >> int Left_Index = ((index * -1) -1);
> >> return Left[Left_Index];
> >> }
> >>
> >> void Tape_Type::Output()
> >> {
> >> printf("Tape_Type::Output()\n");
> >>
> >> if (Left.size())
> >> {
> >> int Last_One = Left.size() - 1;
> >> for (int N = Last_One; N >= 0; N--)
> >> {
> >> int TH = (N + 1) * -1; // determine Tape_Head from N
> >> printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
> >> }
> >> }
> >> if (Right.size())
> >> for (int N = 0; N < Right.size(); N++)
> >> printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
> >> }
> >>
> >> void Tape_Type::move_left()
> >> {
> >> Tape_Head--;
> >> int Left_Index = ((Tape_Head * -1) -1);
> >> if (Left_Index == Left.size())
> >> Left.push_back('_');
> >> }
> >>
> >> void Tape_Type::move_right()
> >> {
> >> Tape_Head++;
> >> if (Tape_Head == Right.size())
> >> Right.push_back('_');
> >> }
> >
> > It might be a more appropriate solution than std::deque for your
> > specific use-case however it is NOT an improvement to std::deque for
> > the general case -- see my reply in the other thread for why.
> >
> > /Flibble
> >
>
> I didn't see any reason why it would not make a better std::deque.
Because it doesn't meet the complexity and referential integrity
requirements of std::deque.
/Flibble
[toc] | [prev] | [next] | [standalone]
| From | olcott <NoOne@NoWhere.com> |
|---|---|
| Date | 2022-05-12 18:38 -0500 |
| Message-ID | <-s-dncjVifoXB-D_nZ2dnUU7_83NnZ2d@giganews.com> |
| In reply to | #50317 |
On 5/12/2022 6:22 PM, Mr Flibble wrote:
> On Thu, 12 May 2022 18:09:39 -0500
> olcott <NoOne@NoWhere.com> wrote:
>
>> On 5/12/2022 5:56 PM, Mr Flibble wrote:
>>> On Thu, 12 May 2022 17:51:25 -0500
>>> olcott <NoOne@NoWhere.com> wrote:
>>>
>>>> C/C++ people please critique this as the basis for an improvement
>>>> to std::deque. It seems to have the key functionality of
>>>> std::deque and does it much more simply while saving time and
>>>> space. https://www.cplusplus.com/reference/deque/deque/
>>>>
>>>> #define tape_element unsigned char
>>>>
>>>> class Tape_Type
>>>> {
>>>> private:
>>>> int Tape_Head = 0; // Can be negative
>>>> std::vector<tape_element> Left; // Stores left expansion
>>>> std::vector<tape_element> Right; // Stores right expansion
>>>> tape_element & operator[](int index);
>>>>
>>>> public:
>>>> void move_left(); // Tape_Head--; Left.push_back(0); as
>>>> needed void move_right(); // Tape_Head++; Left.push_back(0);
>>>> as needed void Write(tape_element Y){ this->operator[](Tape_Head)
>>>> = Y; }; tape_element Read() { return
>>>> this->operator[](Tape_Head); }; Tape_Type(){ Right.push_back('_');
>>>> } // constructor void Output();
>>>> };
>>>>
>>>> tape_element& Tape_Type::operator[](int index)
>>>> {
>>>> if (index > 0)
>>>> return Right[index];
>>>> int Left_Index = ((index * -1) -1);
>>>> return Left[Left_Index];
>>>> }
>>>>
>>>> void Tape_Type::Output()
>>>> {
>>>> printf("Tape_Type::Output()\n");
>>>>
>>>> if (Left.size())
>>>> {
>>>> int Last_One = Left.size() - 1;
>>>> for (int N = Last_One; N >= 0; N--)
>>>> {
>>>> int TH = (N + 1) * -1; // determine Tape_Head from N
>>>> printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
>>>> }
>>>> }
>>>> if (Right.size())
>>>> for (int N = 0; N < Right.size(); N++)
>>>> printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
>>>> }
>>>>
>>>> void Tape_Type::move_left()
>>>> {
>>>> Tape_Head--;
>>>> int Left_Index = ((Tape_Head * -1) -1);
>>>> if (Left_Index == Left.size())
>>>> Left.push_back('_');
>>>> }
>>>>
>>>> void Tape_Type::move_right()
>>>> {
>>>> Tape_Head++;
>>>> if (Tape_Head == Right.size())
>>>> Right.push_back('_');
>>>> }
>>>
>>> It might be a more appropriate solution than std::deque for your
>>> specific use-case however it is NOT an improvement to std::deque for
>>> the general case -- see my reply in the other thread for why.
>>>
>>> /Flibble
>>>
>>
>> I didn't see any reason why it would not make a better std::deque.
>
> Because it doesn't meet the complexity and referential integrity
> requirements of std::deque.
>
> /Flibble
>
It is faster then std::deque.
I couldn't find what you mean by referential integrity it has too many
different meanings. invalidating iterators seemed to be what you mean
otherwise I have no idea.
--
Copyright 2022 Pete Olcott
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
[toc] | [prev] | [next] | [standalone]
| From | Mr Flibble <flibble@reddwarf.jmc> |
|---|---|
| Date | 2022-05-13 00:40 +0100 |
| Message-ID | <20220513004049.00000d64@reddwarf.jmc> |
| In reply to | #50323 |
On Thu, 12 May 2022 18:38:49 -0500
olcott <NoOne@NoWhere.com> wrote:
> On 5/12/2022 6:22 PM, Mr Flibble wrote:
> > On Thu, 12 May 2022 18:09:39 -0500
> > olcott <NoOne@NoWhere.com> wrote:
> >
> >> On 5/12/2022 5:56 PM, Mr Flibble wrote:
> >>> On Thu, 12 May 2022 17:51:25 -0500
> >>> olcott <NoOne@NoWhere.com> wrote:
> >>>
> >>>> C/C++ people please critique this as the basis for an improvement
> >>>> to std::deque. It seems to have the key functionality of
> >>>> std::deque and does it much more simply while saving time and
> >>>> space. https://www.cplusplus.com/reference/deque/deque/
> >>>>
> >>>> #define tape_element unsigned char
> >>>>
> >>>> class Tape_Type
> >>>> {
> >>>> private:
> >>>> int Tape_Head = 0; // Can be negative
> >>>> std::vector<tape_element> Left; // Stores left expansion
> >>>> std::vector<tape_element> Right; // Stores right expansion
> >>>> tape_element & operator[](int index);
> >>>>
> >>>> public:
> >>>> void move_left(); // Tape_Head--; Left.push_back(0); as
> >>>> needed void move_right(); // Tape_Head++; Left.push_back(0);
> >>>> as needed void Write(tape_element Y){ this->operator[](Tape_Head)
> >>>> = Y; }; tape_element Read() { return
> >>>> this->operator[](Tape_Head); }; Tape_Type(){
> >>>> Right.push_back('_'); } // constructor void Output();
> >>>> };
> >>>>
> >>>> tape_element& Tape_Type::operator[](int index)
> >>>> {
> >>>> if (index > 0)
> >>>> return Right[index];
> >>>> int Left_Index = ((index * -1) -1);
> >>>> return Left[Left_Index];
> >>>> }
> >>>>
> >>>> void Tape_Type::Output()
> >>>> {
> >>>> printf("Tape_Type::Output()\n");
> >>>>
> >>>> if (Left.size())
> >>>> {
> >>>> int Last_One = Left.size() - 1;
> >>>> for (int N = Last_One; N >= 0; N--)
> >>>> {
> >>>> int TH = (N + 1) * -1; // determine Tape_Head from N
> >>>> printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
> >>>> }
> >>>> }
> >>>> if (Right.size())
> >>>> for (int N = 0; N < Right.size(); N++)
> >>>> printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
> >>>> }
> >>>>
> >>>> void Tape_Type::move_left()
> >>>> {
> >>>> Tape_Head--;
> >>>> int Left_Index = ((Tape_Head * -1) -1);
> >>>> if (Left_Index == Left.size())
> >>>> Left.push_back('_');
> >>>> }
> >>>>
> >>>> void Tape_Type::move_right()
> >>>> {
> >>>> Tape_Head++;
> >>>> if (Tape_Head == Right.size())
> >>>> Right.push_back('_');
> >>>> }
> >>>
> >>> It might be a more appropriate solution than std::deque for your
> >>> specific use-case however it is NOT an improvement to std::deque
> >>> for the general case -- see my reply in the other thread for why.
> >>>
> >>> /Flibble
> >>>
> >>
> >> I didn't see any reason why it would not make a better std::deque.
> >>
> >
> > Because it doesn't meet the complexity and referential integrity
> > requirements of std::deque.
> >
> > /Flibble
> >
>
> It is faster then std::deque.
> I couldn't find what you mean by referential integrity it has too
> many different meanings. invalidating iterators seemed to be what you
> mean otherwise I have no idea.
I see you are choosing to ignore my reply in the other thread. OK, I
will repost why you are wrong here:
* referential integrity and iterator invalidation are different
things: when you add or remove elements to either end of a
std::deque iterators are indeed invalidated however references to
existing elements remain valid
* If you do 1000 push_fronts followed by 1000 push_backs followed by
1000 pop_fronts all is good however your next pop_front will have
linear complexity, O(n), as it will necessitate removal of the first
element of the right std::vector.
/Flibble
[toc] | [prev] | [next] | [standalone]
| From | olcott <NoOne@NoWhere.com> |
|---|---|
| Date | 2022-05-12 18:49 -0500 |
| Message-ID | <HYudneQqVdKFAOD_nZ2dnUU7_83NnZ2d@giganews.com> |
| In reply to | #50324 |
On 5/12/2022 6:40 PM, Mr Flibble wrote:
> On Thu, 12 May 2022 18:38:49 -0500
> olcott <NoOne@NoWhere.com> wrote:
>
>> On 5/12/2022 6:22 PM, Mr Flibble wrote:
>>> On Thu, 12 May 2022 18:09:39 -0500
>>> olcott <NoOne@NoWhere.com> wrote:
>>>
>>>> On 5/12/2022 5:56 PM, Mr Flibble wrote:
>>>>> On Thu, 12 May 2022 17:51:25 -0500
>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>
>>>>>> C/C++ people please critique this as the basis for an improvement
>>>>>> to std::deque. It seems to have the key functionality of
>>>>>> std::deque and does it much more simply while saving time and
>>>>>> space. https://www.cplusplus.com/reference/deque/deque/
>>>>>>
>>>>>> #define tape_element unsigned char
>>>>>>
>>>>>> class Tape_Type
>>>>>> {
>>>>>> private:
>>>>>> int Tape_Head = 0; // Can be negative
>>>>>> std::vector<tape_element> Left; // Stores left expansion
>>>>>> std::vector<tape_element> Right; // Stores right expansion
>>>>>> tape_element & operator[](int index);
>>>>>>
>>>>>> public:
>>>>>> void move_left(); // Tape_Head--; Left.push_back(0); as
>>>>>> needed void move_right(); // Tape_Head++; Left.push_back(0);
>>>>>> as needed void Write(tape_element Y){ this->operator[](Tape_Head)
>>>>>> = Y; }; tape_element Read() { return
>>>>>> this->operator[](Tape_Head); }; Tape_Type(){
>>>>>> Right.push_back('_'); } // constructor void Output();
>>>>>> };
>>>>>>
>>>>>> tape_element& Tape_Type::operator[](int index)
>>>>>> {
>>>>>> if (index > 0)
>>>>>> return Right[index];
>>>>>> int Left_Index = ((index * -1) -1);
>>>>>> return Left[Left_Index];
>>>>>> }
>>>>>>
>>>>>> void Tape_Type::Output()
>>>>>> {
>>>>>> printf("Tape_Type::Output()\n");
>>>>>>
>>>>>> if (Left.size())
>>>>>> {
>>>>>> int Last_One = Left.size() - 1;
>>>>>> for (int N = Last_One; N >= 0; N--)
>>>>>> {
>>>>>> int TH = (N + 1) * -1; // determine Tape_Head from N
>>>>>> printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
>>>>>> }
>>>>>> }
>>>>>> if (Right.size())
>>>>>> for (int N = 0; N < Right.size(); N++)
>>>>>> printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
>>>>>> }
>>>>>>
>>>>>> void Tape_Type::move_left()
>>>>>> {
>>>>>> Tape_Head--;
>>>>>> int Left_Index = ((Tape_Head * -1) -1);
>>>>>> if (Left_Index == Left.size())
>>>>>> Left.push_back('_');
>>>>>> }
>>>>>>
>>>>>> void Tape_Type::move_right()
>>>>>> {
>>>>>> Tape_Head++;
>>>>>> if (Tape_Head == Right.size())
>>>>>> Right.push_back('_');
>>>>>> }
>>>>>
>>>>> It might be a more appropriate solution than std::deque for your
>>>>> specific use-case however it is NOT an improvement to std::deque
>>>>> for the general case -- see my reply in the other thread for why.
>>>>>
>>>>> /Flibble
>>>>>
>>>>
>>>> I didn't see any reason why it would not make a better std::deque.
>>>>
>>>
>>> Because it doesn't meet the complexity and referential integrity
>>> requirements of std::deque.
>>>
>>> /Flibble
>>>
>>
>> It is faster then std::deque.
>> I couldn't find what you mean by referential integrity it has too
>> many different meanings. invalidating iterators seemed to be what you
>> mean otherwise I have no idea.
>
> I see you are choosing to ignore my reply in the other thread. OK, I
> will repost why you are wrong here:
>
> * referential integrity and iterator invalidation are different
> things: when you add or remove elements to either end of a
> std::deque iterators are indeed invalidated however references to
> existing elements remain valid
Mine words the same way and has the added benefit of contiguous storage.
> * If you do 1000 push_fronts followed by 1000 push_backs followed by
> 1000 pop_fronts all is good however your next pop_front will have
> linear complexity, O(n), as it will necessitate removal of the first
> element of the right std::vector.
I don't think that this applies to the way that I implemented it.
pop_front pops from the end of Left. pop_back pops from the end of
Right. This is the key aspect that I used from David's two-stack approach.
--
Copyright 2022 Pete Olcott
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
[toc] | [prev] | [next] | [standalone]
| From | Mr Flibble <flibble@reddwarf.jmc> |
|---|---|
| Date | 2022-05-13 00:53 +0100 |
| Message-ID | <20220513005340.00001694@reddwarf.jmc> |
| In reply to | #50326 |
On Thu, 12 May 2022 18:49:43 -0500
olcott <NoOne@NoWhere.com> wrote:
> On 5/12/2022 6:40 PM, Mr Flibble wrote:
> > On Thu, 12 May 2022 18:38:49 -0500
> > olcott <NoOne@NoWhere.com> wrote:
> >
> >> On 5/12/2022 6:22 PM, Mr Flibble wrote:
> >>> On Thu, 12 May 2022 18:09:39 -0500
> >>> olcott <NoOne@NoWhere.com> wrote:
> >>>
> >>>> On 5/12/2022 5:56 PM, Mr Flibble wrote:
> >>>>> On Thu, 12 May 2022 17:51:25 -0500
> >>>>> olcott <NoOne@NoWhere.com> wrote:
> >>>>>
> >>>>>> C/C++ people please critique this as the basis for an
> >>>>>> improvement to std::deque. It seems to have the key
> >>>>>> functionality of std::deque and does it much more simply while
> >>>>>> saving time and space.
> >>>>>> https://www.cplusplus.com/reference/deque/deque/
> >>>>>>
> >>>>>> #define tape_element unsigned char
> >>>>>>
> >>>>>> class Tape_Type
> >>>>>> {
> >>>>>> private:
> >>>>>> int Tape_Head = 0; // Can be negative
> >>>>>> std::vector<tape_element> Left; // Stores left expansion
> >>>>>> std::vector<tape_element> Right; // Stores right
> >>>>>> expansion tape_element & operator[](int index);
> >>>>>>
> >>>>>> public:
> >>>>>> void move_left(); // Tape_Head--;
> >>>>>> Left.push_back(0); as needed void move_right(); //
> >>>>>> Tape_Head++; Left.push_back(0); as needed void
> >>>>>> Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
> >>>>>> tape_element Read() { return
> >>>>>> this->operator[](Tape_Head); }; Tape_Type(){
> >>>>>> Right.push_back('_'); } // constructor void Output(); };
> >>>>>>
> >>>>>> tape_element& Tape_Type::operator[](int index)
> >>>>>> {
> >>>>>> if (index > 0)
> >>>>>> return Right[index];
> >>>>>> int Left_Index = ((index * -1) -1);
> >>>>>> return Left[Left_Index];
> >>>>>> }
> >>>>>>
> >>>>>> void Tape_Type::Output()
> >>>>>> {
> >>>>>> printf("Tape_Type::Output()\n");
> >>>>>>
> >>>>>> if (Left.size())
> >>>>>> {
> >>>>>> int Last_One = Left.size() - 1;
> >>>>>> for (int N = Last_One; N >= 0; N--)
> >>>>>> {
> >>>>>> int TH = (N + 1) * -1; // determine Tape_Head from N
> >>>>>> printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
> >>>>>> }
> >>>>>> }
> >>>>>> if (Right.size())
> >>>>>> for (int N = 0; N < Right.size(); N++)
> >>>>>> printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
> >>>>>> }
> >>>>>>
> >>>>>> void Tape_Type::move_left()
> >>>>>> {
> >>>>>> Tape_Head--;
> >>>>>> int Left_Index = ((Tape_Head * -1) -1);
> >>>>>> if (Left_Index == Left.size())
> >>>>>> Left.push_back('_');
> >>>>>> }
> >>>>>>
> >>>>>> void Tape_Type::move_right()
> >>>>>> {
> >>>>>> Tape_Head++;
> >>>>>> if (Tape_Head == Right.size())
> >>>>>> Right.push_back('_');
> >>>>>> }
> >>>>>
> >>>>> It might be a more appropriate solution than std::deque for your
> >>>>> specific use-case however it is NOT an improvement to std::deque
> >>>>> for the general case -- see my reply in the other thread for
> >>>>> why.
> >>>>>
> >>>>> /Flibble
> >>>>>
> >>>>
> >>>> I didn't see any reason why it would not make a better
> >>>> std::deque.
> >>>
> >>> Because it doesn't meet the complexity and referential integrity
> >>> requirements of std::deque.
> >>>
> >>> /Flibble
> >>>
> >>
> >> It is faster then std::deque.
> >> I couldn't find what you mean by referential integrity it has too
> >> many different meanings. invalidating iterators seemed to be what
> >> you mean otherwise I have no idea.
> >
> > I see you are choosing to ignore my reply in the other thread. OK, I
> > will repost why you are wrong here:
> >
> > * referential integrity and iterator invalidation are different
> > things: when you add or remove elements to either end of a
> > std::deque iterators are indeed invalidated however references
> > to existing elements remain valid
>
> Mine words the same way and has the added benefit of contiguous
> storage.
>
> > * If you do 1000 push_fronts followed by 1000 push_backs followed
> > by 1000 pop_fronts all is good however your next pop_front will have
> > linear complexity, O(n), as it will necessitate removal of the
> > first element of the right std::vector.
>
> I don't think that this applies to the way that I implemented it.
> pop_front pops from the end of Left. pop_back pops from the end of
> Right. This is the key aspect that I used from David's two-stack
> approach.
Then it is totally different to what std::deque offers: std::deque
allows ALL elements to be either popped from the front or back. Try
reading AND UNDERSTANDING what I wrote again.
/Flibble
[toc] | [prev] | [next] | [standalone]
| From | olcott <NoOne@NoWhere.com> |
|---|---|
| Date | 2022-05-12 19:12 -0500 |
| Message-ID | <Bo-dnemL1eT6P-D_nZ2dnUU7_81g4p2d@giganews.com> |
| In reply to | #50327 |
On 5/12/2022 6:53 PM, Mr Flibble wrote:
> On Thu, 12 May 2022 18:49:43 -0500
> olcott <NoOne@NoWhere.com> wrote:
>
>> On 5/12/2022 6:40 PM, Mr Flibble wrote:
>>> On Thu, 12 May 2022 18:38:49 -0500
>>> olcott <NoOne@NoWhere.com> wrote:
>>>
>>>> On 5/12/2022 6:22 PM, Mr Flibble wrote:
>>>>> On Thu, 12 May 2022 18:09:39 -0500
>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>
>>>>>> On 5/12/2022 5:56 PM, Mr Flibble wrote:
>>>>>>> On Thu, 12 May 2022 17:51:25 -0500
>>>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>>>
>>>>>>>> C/C++ people please critique this as the basis for an
>>>>>>>> improvement to std::deque. It seems to have the key
>>>>>>>> functionality of std::deque and does it much more simply while
>>>>>>>> saving time and space.
>>>>>>>> https://www.cplusplus.com/reference/deque/deque/
>>>>>>>>
>>>>>>>> #define tape_element unsigned char
>>>>>>>>
>>>>>>>> class Tape_Type
>>>>>>>> {
>>>>>>>> private:
>>>>>>>> int Tape_Head = 0; // Can be negative
>>>>>>>> std::vector<tape_element> Left; // Stores left expansion
>>>>>>>> std::vector<tape_element> Right; // Stores right
>>>>>>>> expansion tape_element & operator[](int index);
>>>>>>>>
>>>>>>>> public:
>>>>>>>> void move_left(); // Tape_Head--;
>>>>>>>> Left.push_back(0); as needed void move_right(); //
>>>>>>>> Tape_Head++; Left.push_back(0); as needed void
>>>>>>>> Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
>>>>>>>> tape_element Read() { return
>>>>>>>> this->operator[](Tape_Head); }; Tape_Type(){
>>>>>>>> Right.push_back('_'); } // constructor void Output(); };
>>>>>>>>
>>>>>>>> tape_element& Tape_Type::operator[](int index)
>>>>>>>> {
>>>>>>>> if (index > 0)
>>>>>>>> return Right[index];
>>>>>>>> int Left_Index = ((index * -1) -1);
>>>>>>>> return Left[Left_Index];
>>>>>>>> }
>>>>>>>>
>>>>>>>> void Tape_Type::Output()
>>>>>>>> {
>>>>>>>> printf("Tape_Type::Output()\n");
>>>>>>>>
>>>>>>>> if (Left.size())
>>>>>>>> {
>>>>>>>> int Last_One = Left.size() - 1;
>>>>>>>> for (int N = Last_One; N >= 0; N--)
>>>>>>>> {
>>>>>>>> int TH = (N + 1) * -1; // determine Tape_Head from N
>>>>>>>> printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
>>>>>>>> }
>>>>>>>> }
>>>>>>>> if (Right.size())
>>>>>>>> for (int N = 0; N < Right.size(); N++)
>>>>>>>> printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
>>>>>>>> }
>>>>>>>>
>>>>>>>> void Tape_Type::move_left()
>>>>>>>> {
>>>>>>>> Tape_Head--;
>>>>>>>> int Left_Index = ((Tape_Head * -1) -1);
>>>>>>>> if (Left_Index == Left.size())
>>>>>>>> Left.push_back('_');
>>>>>>>> }
>>>>>>>>
>>>>>>>> void Tape_Type::move_right()
>>>>>>>> {
>>>>>>>> Tape_Head++;
>>>>>>>> if (Tape_Head == Right.size())
>>>>>>>> Right.push_back('_');
>>>>>>>> }
>>>>>>>
>>>>>>> It might be a more appropriate solution than std::deque for your
>>>>>>> specific use-case however it is NOT an improvement to std::deque
>>>>>>> for the general case -- see my reply in the other thread for
>>>>>>> why.
>>>>>>>
>>>>>>> /Flibble
>>>>>>>
>>>>>>
>>>>>> I didn't see any reason why it would not make a better
>>>>>> std::deque.
>>>>>
>>>>> Because it doesn't meet the complexity and referential integrity
>>>>> requirements of std::deque.
>>>>>
>>>>> /Flibble
>>>>>
>>>>
>>>> It is faster then std::deque.
>>>> I couldn't find what you mean by referential integrity it has too
>>>> many different meanings. invalidating iterators seemed to be what
>>>> you mean otherwise I have no idea.
>>>
>>> I see you are choosing to ignore my reply in the other thread. OK, I
>>> will repost why you are wrong here:
>>>
>>> * referential integrity and iterator invalidation are different
>>> things: when you add or remove elements to either end of a
>>> std::deque iterators are indeed invalidated however references
>>> to existing elements remain valid
>>
>> Mine words the same way and has the added benefit of contiguous
>> storage.
>>
>>> * If you do 1000 push_fronts followed by 1000 push_backs followed
>>> by 1000 pop_fronts all is good however your next pop_front will have
>>> linear complexity, O(n), as it will necessitate removal of the
>>> first element of the right std::vector.
>>
>> I don't think that this applies to the way that I implemented it.
>> pop_front pops from the end of Left. pop_back pops from the end of
>> Right. This is the key aspect that I used from David's two-stack
>> approach.
>
> Then it is totally different to what std::deque offers: std::deque
> allows ALL elements to be either popped from the front or back. Try
> reading AND UNDERSTANDING what I wrote again.
>
> /Flibble
>
I could allow all elements to be popped from the front or the back too.
Mine is much faster when you need far less than all elements.
--
Copyright 2022 Pete Olcott
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
[toc] | [prev] | [next] | [standalone]
| From | Mr Flibble <flibble@reddwarf.jmc> |
|---|---|
| Date | 2022-05-13 01:58 +0100 |
| Message-ID | <20220513015816.00006f57@reddwarf.jmc> |
| In reply to | #50331 |
On Thu, 12 May 2022 19:12:22 -0500
olcott <NoOne@NoWhere.com> wrote:
> On 5/12/2022 6:53 PM, Mr Flibble wrote:
> > On Thu, 12 May 2022 18:49:43 -0500
> > olcott <NoOne@NoWhere.com> wrote:
> >
> >> On 5/12/2022 6:40 PM, Mr Flibble wrote:
> >>> On Thu, 12 May 2022 18:38:49 -0500
> >>> olcott <NoOne@NoWhere.com> wrote:
> >>>
> >>>> On 5/12/2022 6:22 PM, Mr Flibble wrote:
> >>>>> On Thu, 12 May 2022 18:09:39 -0500
> >>>>> olcott <NoOne@NoWhere.com> wrote:
> >>>>>
> >>>>>> On 5/12/2022 5:56 PM, Mr Flibble wrote:
> >>>>>>> On Thu, 12 May 2022 17:51:25 -0500
> >>>>>>> olcott <NoOne@NoWhere.com> wrote:
> >>>>>>>
> >>>>>>>> C/C++ people please critique this as the basis for an
> >>>>>>>> improvement to std::deque. It seems to have the key
> >>>>>>>> functionality of std::deque and does it much more simply
> >>>>>>>> while saving time and space.
> >>>>>>>> https://www.cplusplus.com/reference/deque/deque/
> >>>>>>>>
> >>>>>>>> #define tape_element unsigned char
> >>>>>>>>
> >>>>>>>> class Tape_Type
> >>>>>>>> {
> >>>>>>>> private:
> >>>>>>>> int Tape_Head = 0; // Can be negative
> >>>>>>>> std::vector<tape_element> Left; // Stores left
> >>>>>>>> expansion std::vector<tape_element> Right; // Stores right
> >>>>>>>> expansion tape_element & operator[](int index);
> >>>>>>>>
> >>>>>>>> public:
> >>>>>>>> void move_left(); // Tape_Head--;
> >>>>>>>> Left.push_back(0); as needed void move_right(); //
> >>>>>>>> Tape_Head++; Left.push_back(0); as needed void
> >>>>>>>> Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
> >>>>>>>> tape_element Read() { return
> >>>>>>>> this->operator[](Tape_Head); }; Tape_Type(){
> >>>>>>>> Right.push_back('_'); } // constructor void Output(); };
> >>>>>>>>
> >>>>>>>> tape_element& Tape_Type::operator[](int index)
> >>>>>>>> {
> >>>>>>>> if (index > 0)
> >>>>>>>> return Right[index];
> >>>>>>>> int Left_Index = ((index * -1) -1);
> >>>>>>>> return Left[Left_Index];
> >>>>>>>> }
> >>>>>>>>
> >>>>>>>> void Tape_Type::Output()
> >>>>>>>> {
> >>>>>>>> printf("Tape_Type::Output()\n");
> >>>>>>>>
> >>>>>>>> if (Left.size())
> >>>>>>>> {
> >>>>>>>> int Last_One = Left.size() - 1;
> >>>>>>>> for (int N = Last_One; N >= 0; N--)
> >>>>>>>> {
> >>>>>>>> int TH = (N + 1) * -1; // determine Tape_Head
> >>>>>>>> from N printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
> >>>>>>>> }
> >>>>>>>> }
> >>>>>>>> if (Right.size())
> >>>>>>>> for (int N = 0; N < Right.size(); N++)
> >>>>>>>> printf("[%04d]:%c Right[%02d]\n", N, Right[N],
> >>>>>>>> N); }
> >>>>>>>>
> >>>>>>>> void Tape_Type::move_left()
> >>>>>>>> {
> >>>>>>>> Tape_Head--;
> >>>>>>>> int Left_Index = ((Tape_Head * -1) -1);
> >>>>>>>> if (Left_Index == Left.size())
> >>>>>>>> Left.push_back('_');
> >>>>>>>> }
> >>>>>>>>
> >>>>>>>> void Tape_Type::move_right()
> >>>>>>>> {
> >>>>>>>> Tape_Head++;
> >>>>>>>> if (Tape_Head == Right.size())
> >>>>>>>> Right.push_back('_');
> >>>>>>>> }
> >>>>>>>
> >>>>>>> It might be a more appropriate solution than std::deque for
> >>>>>>> your specific use-case however it is NOT an improvement to
> >>>>>>> std::deque for the general case -- see my reply in the other
> >>>>>>> thread for why.
> >>>>>>>
> >>>>>>> /Flibble
> >>>>>>>
> >>>>>>
> >>>>>> I didn't see any reason why it would not make a better
> >>>>>> std::deque.
> >>>>>
> >>>>> Because it doesn't meet the complexity and referential integrity
> >>>>> requirements of std::deque.
> >>>>>
> >>>>> /Flibble
> >>>>>
> >>>>
> >>>> It is faster then std::deque.
> >>>> I couldn't find what you mean by referential integrity it has too
> >>>> many different meanings. invalidating iterators seemed to be what
> >>>> you mean otherwise I have no idea.
> >>>
> >>> I see you are choosing to ignore my reply in the other thread.
> >>> OK, I will repost why you are wrong here:
> >>>
> >>> * referential integrity and iterator invalidation are different
> >>> things: when you add or remove elements to either end of a
> >>> std::deque iterators are indeed invalidated however
> >>> references to existing elements remain valid
> >>
> >> Mine words the same way and has the added benefit of contiguous
> >> storage.
> >>
> >>> * If you do 1000 push_fronts followed by 1000 push_backs
> >>> followed by 1000 pop_fronts all is good however your next
> >>> pop_front will have linear complexity, O(n), as it will
> >>> necessitate removal of the first element of the right
> >>> std::vector.
> >>
> >> I don't think that this applies to the way that I implemented it.
> >> pop_front pops from the end of Left. pop_back pops from the end of
> >> Right. This is the key aspect that I used from David's two-stack
> >> approach.
> >
> > Then it is totally different to what std::deque offers: std::deque
> > allows ALL elements to be either popped from the front or back. Try
> > reading AND UNDERSTANDING what I wrote again.
> >
> > /Flibble
> >
>
> I could allow all elements to be popped from the front or the back
> too. Mine is much faster when you need far less than all elements.
What you have does not offer what std::deque offers so is not
equivalent to std::deque so can't be considered better than std::deque
for the general case (I don't care about your specific use-case).
/Flibble
[toc] | [prev] | [next] | [standalone]
| From | olcott <NoOne@NoWhere.com> |
|---|---|
| Date | 2022-05-12 20:34 -0500 |
| Message-ID | <D7WdnSjo4swvKOD_nZ2dnUU7_81g4p2d@giganews.com> |
| In reply to | #50337 |
On 5/12/2022 7:58 PM, Mr Flibble wrote:
> On Thu, 12 May 2022 19:12:22 -0500
> olcott <NoOne@NoWhere.com> wrote:
>
>> On 5/12/2022 6:53 PM, Mr Flibble wrote:
>>> On Thu, 12 May 2022 18:49:43 -0500
>>> olcott <NoOne@NoWhere.com> wrote:
>>>
>>>> On 5/12/2022 6:40 PM, Mr Flibble wrote:
>>>>> On Thu, 12 May 2022 18:38:49 -0500
>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>
>>>>>> On 5/12/2022 6:22 PM, Mr Flibble wrote:
>>>>>>> On Thu, 12 May 2022 18:09:39 -0500
>>>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>>>
>>>>>>>> On 5/12/2022 5:56 PM, Mr Flibble wrote:
>>>>>>>>> On Thu, 12 May 2022 17:51:25 -0500
>>>>>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>>>>>
>>>>>>>>>> C/C++ people please critique this as the basis for an
>>>>>>>>>> improvement to std::deque. It seems to have the key
>>>>>>>>>> functionality of std::deque and does it much more simply
>>>>>>>>>> while saving time and space.
>>>>>>>>>> https://www.cplusplus.com/reference/deque/deque/
>>>>>>>>>>
>>>>>>>>>> #define tape_element unsigned char
>>>>>>>>>>
>>>>>>>>>> class Tape_Type
>>>>>>>>>> {
>>>>>>>>>> private:
>>>>>>>>>> int Tape_Head = 0; // Can be negative
>>>>>>>>>> std::vector<tape_element> Left; // Stores left
>>>>>>>>>> expansion std::vector<tape_element> Right; // Stores right
>>>>>>>>>> expansion tape_element & operator[](int index);
>>>>>>>>>>
>>>>>>>>>> public:
>>>>>>>>>> void move_left(); // Tape_Head--;
>>>>>>>>>> Left.push_back(0); as needed void move_right(); //
>>>>>>>>>> Tape_Head++; Left.push_back(0); as needed void
>>>>>>>>>> Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
>>>>>>>>>> tape_element Read() { return
>>>>>>>>>> this->operator[](Tape_Head); }; Tape_Type(){
>>>>>>>>>> Right.push_back('_'); } // constructor void Output(); };
>>>>>>>>>>
>>>>>>>>>> tape_element& Tape_Type::operator[](int index)
>>>>>>>>>> {
>>>>>>>>>> if (index > 0)
>>>>>>>>>> return Right[index];
>>>>>>>>>> int Left_Index = ((index * -1) -1);
>>>>>>>>>> return Left[Left_Index];
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> void Tape_Type::Output()
>>>>>>>>>> {
>>>>>>>>>> printf("Tape_Type::Output()\n");
>>>>>>>>>>
>>>>>>>>>> if (Left.size())
>>>>>>>>>> {
>>>>>>>>>> int Last_One = Left.size() - 1;
>>>>>>>>>> for (int N = Last_One; N >= 0; N--)
>>>>>>>>>> {
>>>>>>>>>> int TH = (N + 1) * -1; // determine Tape_Head
>>>>>>>>>> from N printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
>>>>>>>>>> }
>>>>>>>>>> }
>>>>>>>>>> if (Right.size())
>>>>>>>>>> for (int N = 0; N < Right.size(); N++)
>>>>>>>>>> printf("[%04d]:%c Right[%02d]\n", N, Right[N],
>>>>>>>>>> N); }
>>>>>>>>>>
>>>>>>>>>> void Tape_Type::move_left()
>>>>>>>>>> {
>>>>>>>>>> Tape_Head--;
>>>>>>>>>> int Left_Index = ((Tape_Head * -1) -1);
>>>>>>>>>> if (Left_Index == Left.size())
>>>>>>>>>> Left.push_back('_');
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> void Tape_Type::move_right()
>>>>>>>>>> {
>>>>>>>>>> Tape_Head++;
>>>>>>>>>> if (Tape_Head == Right.size())
>>>>>>>>>> Right.push_back('_');
>>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> It might be a more appropriate solution than std::deque for
>>>>>>>>> your specific use-case however it is NOT an improvement to
>>>>>>>>> std::deque for the general case -- see my reply in the other
>>>>>>>>> thread for why.
>>>>>>>>>
>>>>>>>>> /Flibble
>>>>>>>>>
>>>>>>>>
>>>>>>>> I didn't see any reason why it would not make a better
>>>>>>>> std::deque.
>>>>>>>
>>>>>>> Because it doesn't meet the complexity and referential integrity
>>>>>>> requirements of std::deque.
>>>>>>>
>>>>>>> /Flibble
>>>>>>>
>>>>>>
>>>>>> It is faster then std::deque.
>>>>>> I couldn't find what you mean by referential integrity it has too
>>>>>> many different meanings. invalidating iterators seemed to be what
>>>>>> you mean otherwise I have no idea.
>>>>>
>>>>> I see you are choosing to ignore my reply in the other thread.
>>>>> OK, I will repost why you are wrong here:
>>>>>
>>>>> * referential integrity and iterator invalidation are different
>>>>> things: when you add or remove elements to either end of a
>>>>> std::deque iterators are indeed invalidated however
>>>>> references to existing elements remain valid
>>>>
>>>> Mine words the same way and has the added benefit of contiguous
>>>> storage.
>>>>
>>>>> * If you do 1000 push_fronts followed by 1000 push_backs
>>>>> followed by 1000 pop_fronts all is good however your next
>>>>> pop_front will have linear complexity, O(n), as it will
>>>>> necessitate removal of the first element of the right
>>>>> std::vector.
>>>>
>>>> I don't think that this applies to the way that I implemented it.
>>>> pop_front pops from the end of Left. pop_back pops from the end of
>>>> Right. This is the key aspect that I used from David's two-stack
>>>> approach.
>>>
>>> Then it is totally different to what std::deque offers: std::deque
>>> allows ALL elements to be either popped from the front or back. Try
>>> reading AND UNDERSTANDING what I wrote again.
>>>
>>> /Flibble
>>>
>>
>> I could allow all elements to be popped from the front or the back
>> too. Mine is much faster when you need far less than all elements.
>
> What you have does not offer what std::deque offers so is not
All these things can be added and we end up with a simple, faster,
std:deque that has most the conventional overhead and complexity abolished.
> equivalent to std::deque so can't be considered better than std::deque
> for the general case (I don't care about your specific use-case).
>
> /Flibble
>
It just a matter of defining more member functions.
--
Copyright 2022 Pete Olcott
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
[toc] | [prev] | [next] | [standalone]
| From | Mr Flibble <flibble@reddwarf.jmc> |
|---|---|
| Date | 2022-05-13 08:02 +0100 |
| Message-ID | <20220513080247.000077d7@reddwarf.jmc> |
| In reply to | #50342 |
On Thu, 12 May 2022 20:34:41 -0500
olcott <NoOne@NoWhere.com> wrote:
> On 5/12/2022 7:58 PM, Mr Flibble wrote:
> > On Thu, 12 May 2022 19:12:22 -0500
> > olcott <NoOne@NoWhere.com> wrote:
> >
> >> On 5/12/2022 6:53 PM, Mr Flibble wrote:
> >>> On Thu, 12 May 2022 18:49:43 -0500
> >>> olcott <NoOne@NoWhere.com> wrote:
> >>>
> >>>> On 5/12/2022 6:40 PM, Mr Flibble wrote:
> >>>>> On Thu, 12 May 2022 18:38:49 -0500
> >>>>> olcott <NoOne@NoWhere.com> wrote:
> >>>>>
> >>>>>> On 5/12/2022 6:22 PM, Mr Flibble wrote:
> >>>>>>> On Thu, 12 May 2022 18:09:39 -0500
> >>>>>>> olcott <NoOne@NoWhere.com> wrote:
> >>>>>>>
> >>>>>>>> On 5/12/2022 5:56 PM, Mr Flibble wrote:
> >>>>>>>>> On Thu, 12 May 2022 17:51:25 -0500
> >>>>>>>>> olcott <NoOne@NoWhere.com> wrote:
> >>>>>>>>>
> >>>>>>>>>> C/C++ people please critique this as the basis for an
> >>>>>>>>>> improvement to std::deque. It seems to have the key
> >>>>>>>>>> functionality of std::deque and does it much more simply
> >>>>>>>>>> while saving time and space.
> >>>>>>>>>> https://www.cplusplus.com/reference/deque/deque/
> >>>>>>>>>>
> >>>>>>>>>> #define tape_element unsigned char
> >>>>>>>>>>
> >>>>>>>>>> class Tape_Type
> >>>>>>>>>> {
> >>>>>>>>>> private:
> >>>>>>>>>> int Tape_Head = 0; // Can be negative
> >>>>>>>>>> std::vector<tape_element> Left; // Stores left
> >>>>>>>>>> expansion std::vector<tape_element> Right; // Stores right
> >>>>>>>>>> expansion tape_element & operator[](int index);
> >>>>>>>>>>
> >>>>>>>>>> public:
> >>>>>>>>>> void move_left(); // Tape_Head--;
> >>>>>>>>>> Left.push_back(0); as needed void move_right(); //
> >>>>>>>>>> Tape_Head++; Left.push_back(0); as needed void
> >>>>>>>>>> Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
> >>>>>>>>>> tape_element Read() { return
> >>>>>>>>>> this->operator[](Tape_Head); }; Tape_Type(){
> >>>>>>>>>> Right.push_back('_'); } // constructor void Output(); };
> >>>>>>>>>>
> >>>>>>>>>> tape_element& Tape_Type::operator[](int index)
> >>>>>>>>>> {
> >>>>>>>>>> if (index > 0)
> >>>>>>>>>> return Right[index];
> >>>>>>>>>> int Left_Index = ((index * -1) -1);
> >>>>>>>>>> return Left[Left_Index];
> >>>>>>>>>> }
> >>>>>>>>>>
> >>>>>>>>>> void Tape_Type::Output()
> >>>>>>>>>> {
> >>>>>>>>>> printf("Tape_Type::Output()\n");
> >>>>>>>>>>
> >>>>>>>>>> if (Left.size())
> >>>>>>>>>> {
> >>>>>>>>>> int Last_One = Left.size() - 1;
> >>>>>>>>>> for (int N = Last_One; N >= 0; N--)
> >>>>>>>>>> {
> >>>>>>>>>> int TH = (N + 1) * -1; // determine Tape_Head
> >>>>>>>>>> from N printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
> >>>>>>>>>> }
> >>>>>>>>>> }
> >>>>>>>>>> if (Right.size())
> >>>>>>>>>> for (int N = 0; N < Right.size(); N++)
> >>>>>>>>>> printf("[%04d]:%c Right[%02d]\n", N, Right[N],
> >>>>>>>>>> N); }
> >>>>>>>>>>
> >>>>>>>>>> void Tape_Type::move_left()
> >>>>>>>>>> {
> >>>>>>>>>> Tape_Head--;
> >>>>>>>>>> int Left_Index = ((Tape_Head * -1) -1);
> >>>>>>>>>> if (Left_Index == Left.size())
> >>>>>>>>>> Left.push_back('_');
> >>>>>>>>>> }
> >>>>>>>>>>
> >>>>>>>>>> void Tape_Type::move_right()
> >>>>>>>>>> {
> >>>>>>>>>> Tape_Head++;
> >>>>>>>>>> if (Tape_Head == Right.size())
> >>>>>>>>>> Right.push_back('_');
> >>>>>>>>>> }
> >>>>>>>>>
> >>>>>>>>> It might be a more appropriate solution than std::deque for
> >>>>>>>>> your specific use-case however it is NOT an improvement to
> >>>>>>>>> std::deque for the general case -- see my reply in the other
> >>>>>>>>> thread for why.
> >>>>>>>>>
> >>>>>>>>> /Flibble
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>> I didn't see any reason why it would not make a better
> >>>>>>>> std::deque.
> >>>>>>>
> >>>>>>> Because it doesn't meet the complexity and referential
> >>>>>>> integrity requirements of std::deque.
> >>>>>>>
> >>>>>>> /Flibble
> >>>>>>>
> >>>>>>
> >>>>>> It is faster then std::deque.
> >>>>>> I couldn't find what you mean by referential integrity it has
> >>>>>> too many different meanings. invalidating iterators seemed to
> >>>>>> be what you mean otherwise I have no idea.
> >>>>>
> >>>>> I see you are choosing to ignore my reply in the other thread.
> >>>>> OK, I will repost why you are wrong here:
> >>>>>
> >>>>> * referential integrity and iterator invalidation are
> >>>>> different things: when you add or remove elements to either end
> >>>>> of a std::deque iterators are indeed invalidated however
> >>>>> references to existing elements remain valid
> >>>>
> >>>> Mine words the same way and has the added benefit of contiguous
> >>>> storage.
> >>>>
> >>>>> * If you do 1000 push_fronts followed by 1000 push_backs
> >>>>> followed by 1000 pop_fronts all is good however your next
> >>>>> pop_front will have linear complexity, O(n), as it will
> >>>>> necessitate removal of the first element of the right
> >>>>> std::vector.
> >>>>
> >>>> I don't think that this applies to the way that I implemented it.
> >>>> pop_front pops from the end of Left. pop_back pops from the end
> >>>> of Right. This is the key aspect that I used from David's
> >>>> two-stack approach.
> >>>
> >>> Then it is totally different to what std::deque offers: std::deque
> >>> allows ALL elements to be either popped from the front or back.
> >>> Try reading AND UNDERSTANDING what I wrote again.
> >>>
> >>> /Flibble
> >>>
> >>
> >> I could allow all elements to be popped from the front or the back
> >> too. Mine is much faster when you need far less than all elements.
> >>
> >
> > What you have does not offer what std::deque offers so is not
>
> All these things can be added and we end up with a simple, faster,
> std:deque that has most the conventional overhead and complexity
> abolished.
>
> > equivalent to std::deque so can't be considered better than
> > std::deque for the general case (I don't care about your specific
> > use-case).
> >
> > /Flibble
> >
>
> It just a matter of defining more member functions.
You cannot implement all of std::deque's member functions meeting
std::deque requirements using your chosen data structure of two
std::vectors.
/Flibble
[toc] | [prev] | [next] | [standalone]
| From | tth <tth@none.invalid> |
|---|---|
| Date | 2022-05-13 09:10 +0200 |
| Message-ID | <t5l090$2f3k$1@news.gegeweb.eu> |
| In reply to | #50355 |
On 5/13/22 09:02, Mr Flibble wrote:
> You cannot implement all of std::deque's member functions meeting
> std::deque requirements using your chosen data structure of two
> std::vectors.
Not with any version of the C language.
--
+-------------------------------------------------------------------+
| sphinx of black quartz, judge my vow. |
+-------------------------------------------------------------------+
[toc] | [prev] | [next] | [standalone]
| From | olcott <NoOne@NoWhere.com> |
|---|---|
| Date | 2022-05-13 10:58 -0500 |
| Message-ID | <zdmdnV7tirvcHeP_nZ2dnUU7_8xQAAAA@giganews.com> |
| In reply to | #50355 |
On 5/13/2022 2:02 AM, Mr Flibble wrote:
> On Thu, 12 May 2022 20:34:41 -0500
> olcott <NoOne@NoWhere.com> wrote:
>
>> On 5/12/2022 7:58 PM, Mr Flibble wrote:
>>> On Thu, 12 May 2022 19:12:22 -0500
>>> olcott <NoOne@NoWhere.com> wrote:
>>>
>>>> On 5/12/2022 6:53 PM, Mr Flibble wrote:
>>>>> On Thu, 12 May 2022 18:49:43 -0500
>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>
>>>>>> On 5/12/2022 6:40 PM, Mr Flibble wrote:
>>>>>>> On Thu, 12 May 2022 18:38:49 -0500
>>>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>>>
>>>>>>>> On 5/12/2022 6:22 PM, Mr Flibble wrote:
>>>>>>>>> On Thu, 12 May 2022 18:09:39 -0500
>>>>>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>>>>>
>>>>>>>>>> On 5/12/2022 5:56 PM, Mr Flibble wrote:
>>>>>>>>>>> On Thu, 12 May 2022 17:51:25 -0500
>>>>>>>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> C/C++ people please critique this as the basis for an
>>>>>>>>>>>> improvement to std::deque. It seems to have the key
>>>>>>>>>>>> functionality of std::deque and does it much more simply
>>>>>>>>>>>> while saving time and space.
>>>>>>>>>>>> https://www.cplusplus.com/reference/deque/deque/
>>>>>>>>>>>>
>>>>>>>>>>>> #define tape_element unsigned char
>>>>>>>>>>>>
>>>>>>>>>>>> class Tape_Type
>>>>>>>>>>>> {
>>>>>>>>>>>> private:
>>>>>>>>>>>> int Tape_Head = 0; // Can be negative
>>>>>>>>>>>> std::vector<tape_element> Left; // Stores left
>>>>>>>>>>>> expansion std::vector<tape_element> Right; // Stores right
>>>>>>>>>>>> expansion tape_element & operator[](int index);
>>>>>>>>>>>>
>>>>>>>>>>>> public:
>>>>>>>>>>>> void move_left(); // Tape_Head--;
>>>>>>>>>>>> Left.push_back(0); as needed void move_right(); //
>>>>>>>>>>>> Tape_Head++; Left.push_back(0); as needed void
>>>>>>>>>>>> Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
>>>>>>>>>>>> tape_element Read() { return
>>>>>>>>>>>> this->operator[](Tape_Head); }; Tape_Type(){
>>>>>>>>>>>> Right.push_back('_'); } // constructor void Output(); };
>>>>>>>>>>>>
>>>>>>>>>>>> tape_element& Tape_Type::operator[](int index)
>>>>>>>>>>>> {
>>>>>>>>>>>> if (index > 0)
>>>>>>>>>>>> return Right[index];
>>>>>>>>>>>> int Left_Index = ((index * -1) -1);
>>>>>>>>>>>> return Left[Left_Index];
>>>>>>>>>>>> }
>>>>>>>>>>>>
>>>>>>>>>>>> void Tape_Type::Output()
>>>>>>>>>>>> {
>>>>>>>>>>>> printf("Tape_Type::Output()\n");
>>>>>>>>>>>>
>>>>>>>>>>>> if (Left.size())
>>>>>>>>>>>> {
>>>>>>>>>>>> int Last_One = Left.size() - 1;
>>>>>>>>>>>> for (int N = Last_One; N >= 0; N--)
>>>>>>>>>>>> {
>>>>>>>>>>>> int TH = (N + 1) * -1; // determine Tape_Head
>>>>>>>>>>>> from N printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
>>>>>>>>>>>> }
>>>>>>>>>>>> }
>>>>>>>>>>>> if (Right.size())
>>>>>>>>>>>> for (int N = 0; N < Right.size(); N++)
>>>>>>>>>>>> printf("[%04d]:%c Right[%02d]\n", N, Right[N],
>>>>>>>>>>>> N); }
>>>>>>>>>>>>
>>>>>>>>>>>> void Tape_Type::move_left()
>>>>>>>>>>>> {
>>>>>>>>>>>> Tape_Head--;
>>>>>>>>>>>> int Left_Index = ((Tape_Head * -1) -1);
>>>>>>>>>>>> if (Left_Index == Left.size())
>>>>>>>>>>>> Left.push_back('_');
>>>>>>>>>>>> }
>>>>>>>>>>>>
>>>>>>>>>>>> void Tape_Type::move_right()
>>>>>>>>>>>> {
>>>>>>>>>>>> Tape_Head++;
>>>>>>>>>>>> if (Tape_Head == Right.size())
>>>>>>>>>>>> Right.push_back('_');
>>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>> It might be a more appropriate solution than std::deque for
>>>>>>>>>>> your specific use-case however it is NOT an improvement to
>>>>>>>>>>> std::deque for the general case -- see my reply in the other
>>>>>>>>>>> thread for why.
>>>>>>>>>>>
>>>>>>>>>>> /Flibble
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> I didn't see any reason why it would not make a better
>>>>>>>>>> std::deque.
>>>>>>>>>
>>>>>>>>> Because it doesn't meet the complexity and referential
>>>>>>>>> integrity requirements of std::deque.
>>>>>>>>>
>>>>>>>>> /Flibble
>>>>>>>>>
>>>>>>>>
>>>>>>>> It is faster then std::deque.
>>>>>>>> I couldn't find what you mean by referential integrity it has
>>>>>>>> too many different meanings. invalidating iterators seemed to
>>>>>>>> be what you mean otherwise I have no idea.
>>>>>>>
>>>>>>> I see you are choosing to ignore my reply in the other thread.
>>>>>>> OK, I will repost why you are wrong here:
>>>>>>>
>>>>>>> * referential integrity and iterator invalidation are
>>>>>>> different things: when you add or remove elements to either end
>>>>>>> of a std::deque iterators are indeed invalidated however
>>>>>>> references to existing elements remain valid
>>>>>>
>>>>>> Mine words the same way and has the added benefit of contiguous
>>>>>> storage.
>>>>>>
>>>>>>> * If you do 1000 push_fronts followed by 1000 push_backs
>>>>>>> followed by 1000 pop_fronts all is good however your next
>>>>>>> pop_front will have linear complexity, O(n), as it will
>>>>>>> necessitate removal of the first element of the right
>>>>>>> std::vector.
>>>>>>
>>>>>> I don't think that this applies to the way that I implemented it.
>>>>>> pop_front pops from the end of Left. pop_back pops from the end
>>>>>> of Right. This is the key aspect that I used from David's
>>>>>> two-stack approach.
>>>>>
>>>>> Then it is totally different to what std::deque offers: std::deque
>>>>> allows ALL elements to be either popped from the front or back.
>>>>> Try reading AND UNDERSTANDING what I wrote again.
>>>>>
>>>>> /Flibble
>>>>>
>>>>
>>>> I could allow all elements to be popped from the front or the back
>>>> too. Mine is much faster when you need far less than all elements.
>>>>
>>>
>>> What you have does not offer what std::deque offers so is not
>>
>> All these things can be added and we end up with a simple, faster,
>> std:deque that has most the conventional overhead and complexity
>> abolished.
>>
>>> equivalent to std::deque so can't be considered better than
>>> std::deque for the general case (I don't care about your specific
>>> use-case).
>>>
>>> /Flibble
>>>
>>
>> It just a matter of defining more member functions.
>
> You cannot implement all of std::deque's member functions meeting
> std::deque requirements using your chosen data structure of two
> std::vectors.
>
> /Flibble
>
// Tape_Type implements a two-way Turing machine tape.
// Right contains Tape_Head >= 0 values (right expansion)
// Left contains Tape_Head < 0 values (left expansion)
//
// Grows with Right.push_back() as Tape_Head increases above 0.
// Grows with Left.push_back() as Tape_Head decreases below 0.
//
// Tape_Type has functionality very similar to std::deque
// yet implements this functionality much more simply.
// This saves time and space.
//
class Tape_Type
{
public:
typedef unsigned char tape_element;
private:
int Tape_Head = 0; // Can be negative
std::vector<tape_element> Left; // Stores left expansion
std::vector<tape_element> Right; // Stores right expansion
tape_element& operator[](int index)
{
return index >= 0 ? Right[index] : Left[-index - 1];
}
public:
tape_element& front( ) { return Left.back(); }
tape_element& back() { return Right.back(); }
void pop_front() { Left.pop_back(); }
void pop_back() { Right.pop_back(); }
void push_front(tape_element& E) { Left.push_back(E); }
void push_back(tape_element& E) { Right.push_back(E); }
void reserve(unsigned int N)
{ Left.reserve(N); Right.reserve(N); }
--
Copyright 2022 Pete Olcott
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
[toc] | [prev] | [next] | [standalone]
| From | Mr Flibble <flibble@reddwarf.jmc> |
|---|---|
| Date | 2022-05-13 17:02 +0100 |
| Message-ID | <20220513170239.0000273b@reddwarf.jmc> |
| In reply to | #50369 |
On Fri, 13 May 2022 10:58:56 -0500
olcott <NoOne@NoWhere.com> wrote:
> On 5/13/2022 2:02 AM, Mr Flibble wrote:
> > On Thu, 12 May 2022 20:34:41 -0500
> > olcott <NoOne@NoWhere.com> wrote:
> >
> >> On 5/12/2022 7:58 PM, Mr Flibble wrote:
> >>> On Thu, 12 May 2022 19:12:22 -0500
> >>> olcott <NoOne@NoWhere.com> wrote:
> >>>
> >>>> On 5/12/2022 6:53 PM, Mr Flibble wrote:
> >>>>> On Thu, 12 May 2022 18:49:43 -0500
> >>>>> olcott <NoOne@NoWhere.com> wrote:
> >>>>>
> >>>>>> On 5/12/2022 6:40 PM, Mr Flibble wrote:
> >>>>>>> On Thu, 12 May 2022 18:38:49 -0500
> >>>>>>> olcott <NoOne@NoWhere.com> wrote:
> >>>>>>>
> >>>>>>>> On 5/12/2022 6:22 PM, Mr Flibble wrote:
> >>>>>>>>> On Thu, 12 May 2022 18:09:39 -0500
> >>>>>>>>> olcott <NoOne@NoWhere.com> wrote:
> >>>>>>>>>
> >>>>>>>>>> On 5/12/2022 5:56 PM, Mr Flibble wrote:
> >>>>>>>>>>> On Thu, 12 May 2022 17:51:25 -0500
> >>>>>>>>>>> olcott <NoOne@NoWhere.com> wrote:
> >>>>>>>>>>>
> >>>>>>>>>>>> C/C++ people please critique this as the basis for an
> >>>>>>>>>>>> improvement to std::deque. It seems to have the key
> >>>>>>>>>>>> functionality of std::deque and does it much more simply
> >>>>>>>>>>>> while saving time and space.
> >>>>>>>>>>>> https://www.cplusplus.com/reference/deque/deque/
> >>>>>>>>>>>>
> >>>>>>>>>>>> #define tape_element unsigned char
> >>>>>>>>>>>>
> >>>>>>>>>>>> class Tape_Type
> >>>>>>>>>>>> {
> >>>>>>>>>>>> private:
> >>>>>>>>>>>> int Tape_Head = 0; // Can be
> >>>>>>>>>>>> negative std::vector<tape_element> Left; // Stores left
> >>>>>>>>>>>> expansion std::vector<tape_element> Right; // Stores
> >>>>>>>>>>>> right expansion tape_element & operator[](int index);
> >>>>>>>>>>>>
> >>>>>>>>>>>> public:
> >>>>>>>>>>>> void move_left(); // Tape_Head--;
> >>>>>>>>>>>> Left.push_back(0); as needed void move_right(); //
> >>>>>>>>>>>> Tape_Head++; Left.push_back(0); as needed void
> >>>>>>>>>>>> Write(tape_element Y){ this->operator[](Tape_Head) = Y;
> >>>>>>>>>>>> }; tape_element Read() { return
> >>>>>>>>>>>> this->operator[](Tape_Head); }; Tape_Type(){
> >>>>>>>>>>>> Right.push_back('_'); } // constructor void Output(); };
> >>>>>>>>>>>>
> >>>>>>>>>>>> tape_element& Tape_Type::operator[](int index)
> >>>>>>>>>>>> {
> >>>>>>>>>>>> if (index > 0)
> >>>>>>>>>>>> return Right[index];
> >>>>>>>>>>>> int Left_Index = ((index * -1) -1);
> >>>>>>>>>>>> return Left[Left_Index];
> >>>>>>>>>>>> }
> >>>>>>>>>>>>
> >>>>>>>>>>>> void Tape_Type::Output()
> >>>>>>>>>>>> {
> >>>>>>>>>>>> printf("Tape_Type::Output()\n");
> >>>>>>>>>>>>
> >>>>>>>>>>>> if (Left.size())
> >>>>>>>>>>>> {
> >>>>>>>>>>>> int Last_One = Left.size() - 1;
> >>>>>>>>>>>> for (int N = Last_One; N >= 0; N--)
> >>>>>>>>>>>> {
> >>>>>>>>>>>> int TH = (N + 1) * -1; // determine
> >>>>>>>>>>>> Tape_Head from N printf("[%04d]:%c Left[%02d]\n", TH,
> >>>>>>>>>>>> Left[N], N); }
> >>>>>>>>>>>> }
> >>>>>>>>>>>> if (Right.size())
> >>>>>>>>>>>> for (int N = 0; N < Right.size(); N++)
> >>>>>>>>>>>> printf("[%04d]:%c Right[%02d]\n", N,
> >>>>>>>>>>>> Right[N], N); }
> >>>>>>>>>>>>
> >>>>>>>>>>>> void Tape_Type::move_left()
> >>>>>>>>>>>> {
> >>>>>>>>>>>> Tape_Head--;
> >>>>>>>>>>>> int Left_Index = ((Tape_Head * -1) -1);
> >>>>>>>>>>>> if (Left_Index == Left.size())
> >>>>>>>>>>>> Left.push_back('_');
> >>>>>>>>>>>> }
> >>>>>>>>>>>>
> >>>>>>>>>>>> void Tape_Type::move_right()
> >>>>>>>>>>>> {
> >>>>>>>>>>>> Tape_Head++;
> >>>>>>>>>>>> if (Tape_Head == Right.size())
> >>>>>>>>>>>> Right.push_back('_');
> >>>>>>>>>>>> }
> >>>>>>>>>>>
> >>>>>>>>>>> It might be a more appropriate solution than std::deque
> >>>>>>>>>>> for your specific use-case however it is NOT an
> >>>>>>>>>>> improvement to std::deque for the general case -- see my
> >>>>>>>>>>> reply in the other thread for why.
> >>>>>>>>>>>
> >>>>>>>>>>> /Flibble
> >>>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>> I didn't see any reason why it would not make a better
> >>>>>>>>>> std::deque.
> >>>>>>>>>
> >>>>>>>>> Because it doesn't meet the complexity and referential
> >>>>>>>>> integrity requirements of std::deque.
> >>>>>>>>>
> >>>>>>>>> /Flibble
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>> It is faster then std::deque.
> >>>>>>>> I couldn't find what you mean by referential integrity it has
> >>>>>>>> too many different meanings. invalidating iterators seemed to
> >>>>>>>> be what you mean otherwise I have no idea.
> >>>>>>>
> >>>>>>> I see you are choosing to ignore my reply in the other thread.
> >>>>>>> OK, I will repost why you are wrong here:
> >>>>>>>
> >>>>>>> * referential integrity and iterator invalidation are
> >>>>>>> different things: when you add or remove elements to either
> >>>>>>> end of a std::deque iterators are indeed invalidated however
> >>>>>>> references to existing elements remain valid
> >>>>>>
> >>>>>> Mine words the same way and has the added benefit of contiguous
> >>>>>> storage.
> >>>>>>
> >>>>>>> * If you do 1000 push_fronts followed by 1000 push_backs
> >>>>>>> followed by 1000 pop_fronts all is good however your next
> >>>>>>> pop_front will have linear complexity, O(n), as it will
> >>>>>>> necessitate removal of the first element of the right
> >>>>>>> std::vector.
> >>>>>>
> >>>>>> I don't think that this applies to the way that I implemented
> >>>>>> it. pop_front pops from the end of Left. pop_back pops from
> >>>>>> the end of Right. This is the key aspect that I used from
> >>>>>> David's two-stack approach.
> >>>>>
> >>>>> Then it is totally different to what std::deque offers:
> >>>>> std::deque allows ALL elements to be either popped from the
> >>>>> front or back. Try reading AND UNDERSTANDING what I wrote again.
> >>>>>
> >>>>> /Flibble
> >>>>>
> >>>>
> >>>> I could allow all elements to be popped from the front or the
> >>>> back too. Mine is much faster when you need far less than all
> >>>> elements.
> >>>
> >>> What you have does not offer what std::deque offers so is not
> >>
> >> All these things can be added and we end up with a simple, faster,
> >> std:deque that has most the conventional overhead and complexity
> >> abolished.
> >>
> >>> equivalent to std::deque so can't be considered better than
> >>> std::deque for the general case (I don't care about your specific
> >>> use-case).
> >>>
> >>> /Flibble
> >>>
> >>
> >> It just a matter of defining more member functions.
> >
> > You cannot implement all of std::deque's member functions meeting
> > std::deque requirements using your chosen data structure of two
> > std::vectors.
> >
> > /Flibble
> >
>
> // Tape_Type implements a two-way Turing machine tape.
> // Right contains Tape_Head >= 0 values (right expansion)
> // Left contains Tape_Head < 0 values (left expansion)
> //
> // Grows with Right.push_back() as Tape_Head increases above 0.
> // Grows with Left.push_back() as Tape_Head decreases below 0.
> //
> // Tape_Type has functionality very similar to std::deque
> // yet implements this functionality much more simply.
> // This saves time and space.
> //
> class Tape_Type
> {
> public:
> typedef unsigned char tape_element;
>
> private:
> int Tape_Head = 0; // Can be negative
> std::vector<tape_element> Left; // Stores left expansion
> std::vector<tape_element> Right; // Stores right expansion
>
> tape_element& operator[](int index)
> {
> return index >= 0 ? Right[index] : Left[-index - 1];
> }
>
> public:
> tape_element& front( ) { return Left.back(); }
> tape_element& back() { return Right.back(); }
> void pop_front() { Left.pop_back(); }
> void pop_back() { Right.pop_back(); }
> void push_front(tape_element& E) { Left.push_back(E); }
> void push_back(tape_element& E) { Right.push_back(E); }
> void reserve(unsigned int N)
> { Left.reserve(N); Right.reserve(N); }
And what happens if Left is empty, Right is non-empty and you call
pop_front()?
/Flibble
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2022-05-13 12:44 -0700 |
| Message-ID | <t5mce6$ij6$1@dont-email.me> |
| In reply to | #50372 |
On 5/13/2022 9:02 AM, Mr Flibble wrote:
> On Fri, 13 May 2022 10:58:56 -0500
> olcott <NoOne@NoWhere.com> wrote:
>
>> On 5/13/2022 2:02 AM, Mr Flibble wrote:
>>> On Thu, 12 May 2022 20:34:41 -0500
>>> olcott <NoOne@NoWhere.com> wrote:
>>>
>>>> On 5/12/2022 7:58 PM, Mr Flibble wrote:
>>>>> On Thu, 12 May 2022 19:12:22 -0500
>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>
>>>>>> On 5/12/2022 6:53 PM, Mr Flibble wrote:
>>>>>>> On Thu, 12 May 2022 18:49:43 -0500
>>>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>>>
>>>>>>>> On 5/12/2022 6:40 PM, Mr Flibble wrote:
>>>>>>>>> On Thu, 12 May 2022 18:38:49 -0500
>>>>>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>>>>>
>>>>>>>>>> On 5/12/2022 6:22 PM, Mr Flibble wrote:
>>>>>>>>>>> On Thu, 12 May 2022 18:09:39 -0500
>>>>>>>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> On 5/12/2022 5:56 PM, Mr Flibble wrote:
>>>>>>>>>>>>> On Thu, 12 May 2022 17:51:25 -0500
>>>>>>>>>>>>> olcott <NoOne@NoWhere.com> wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>>> C/C++ people please critique this as the basis for an
>>>>>>>>>>>>>> improvement to std::deque. It seems to have the key
>>>>>>>>>>>>>> functionality of std::deque and does it much more simply
>>>>>>>>>>>>>> while saving time and space.
>>>>>>>>>>>>>> https://www.cplusplus.com/reference/deque/deque/
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> #define tape_element unsigned char
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> class Tape_Type
>>>>>>>>>>>>>> {
>>>>>>>>>>>>>> private:
>>>>>>>>>>>>>> int Tape_Head = 0; // Can be
>>>>>>>>>>>>>> negative std::vector<tape_element> Left; // Stores left
>>>>>>>>>>>>>> expansion std::vector<tape_element> Right; // Stores
>>>>>>>>>>>>>> right expansion tape_element & operator[](int index);
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> public:
>>>>>>>>>>>>>> void move_left(); // Tape_Head--;
>>>>>>>>>>>>>> Left.push_back(0); as needed void move_right(); //
>>>>>>>>>>>>>> Tape_Head++; Left.push_back(0); as needed void
>>>>>>>>>>>>>> Write(tape_element Y){ this->operator[](Tape_Head) = Y;
>>>>>>>>>>>>>> }; tape_element Read() { return
>>>>>>>>>>>>>> this->operator[](Tape_Head); }; Tape_Type(){
>>>>>>>>>>>>>> Right.push_back('_'); } // constructor void Output(); };
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> tape_element& Tape_Type::operator[](int index)
>>>>>>>>>>>>>> {
>>>>>>>>>>>>>> if (index > 0)
>>>>>>>>>>>>>> return Right[index];
>>>>>>>>>>>>>> int Left_Index = ((index * -1) -1);
>>>>>>>>>>>>>> return Left[Left_Index];
>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> void Tape_Type::Output()
>>>>>>>>>>>>>> {
>>>>>>>>>>>>>> printf("Tape_Type::Output()\n");
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> if (Left.size())
>>>>>>>>>>>>>> {
>>>>>>>>>>>>>> int Last_One = Left.size() - 1;
>>>>>>>>>>>>>> for (int N = Last_One; N >= 0; N--)
>>>>>>>>>>>>>> {
>>>>>>>>>>>>>> int TH = (N + 1) * -1; // determine
>>>>>>>>>>>>>> Tape_Head from N printf("[%04d]:%c Left[%02d]\n", TH,
>>>>>>>>>>>>>> Left[N], N); }
>>>>>>>>>>>>>> }
>>>>>>>>>>>>>> if (Right.size())
>>>>>>>>>>>>>> for (int N = 0; N < Right.size(); N++)
>>>>>>>>>>>>>> printf("[%04d]:%c Right[%02d]\n", N,
>>>>>>>>>>>>>> Right[N], N); }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> void Tape_Type::move_left()
>>>>>>>>>>>>>> {
>>>>>>>>>>>>>> Tape_Head--;
>>>>>>>>>>>>>> int Left_Index = ((Tape_Head * -1) -1);
>>>>>>>>>>>>>> if (Left_Index == Left.size())
>>>>>>>>>>>>>> Left.push_back('_');
>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> void Tape_Type::move_right()
>>>>>>>>>>>>>> {
>>>>>>>>>>>>>> Tape_Head++;
>>>>>>>>>>>>>> if (Tape_Head == Right.size())
>>>>>>>>>>>>>> Right.push_back('_');
>>>>>>>>>>>>>> }
>>>>>>>>>>>>>
>>>>>>>>>>>>> It might be a more appropriate solution than std::deque
>>>>>>>>>>>>> for your specific use-case however it is NOT an
>>>>>>>>>>>>> improvement to std::deque for the general case -- see my
>>>>>>>>>>>>> reply in the other thread for why.
>>>>>>>>>>>>>
>>>>>>>>>>>>> /Flibble
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> I didn't see any reason why it would not make a better
>>>>>>>>>>>> std::deque.
>>>>>>>>>>>
>>>>>>>>>>> Because it doesn't meet the complexity and referential
>>>>>>>>>>> integrity requirements of std::deque.
>>>>>>>>>>>
>>>>>>>>>>> /Flibble
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> It is faster then std::deque.
>>>>>>>>>> I couldn't find what you mean by referential integrity it has
>>>>>>>>>> too many different meanings. invalidating iterators seemed to
>>>>>>>>>> be what you mean otherwise I have no idea.
>>>>>>>>>
>>>>>>>>> I see you are choosing to ignore my reply in the other thread.
>>>>>>>>> OK, I will repost why you are wrong here:
>>>>>>>>>
>>>>>>>>> * referential integrity and iterator invalidation are
>>>>>>>>> different things: when you add or remove elements to either
>>>>>>>>> end of a std::deque iterators are indeed invalidated however
>>>>>>>>> references to existing elements remain valid
>>>>>>>>
>>>>>>>> Mine words the same way and has the added benefit of contiguous
>>>>>>>> storage.
>>>>>>>>
>>>>>>>>> * If you do 1000 push_fronts followed by 1000 push_backs
>>>>>>>>> followed by 1000 pop_fronts all is good however your next
>>>>>>>>> pop_front will have linear complexity, O(n), as it will
>>>>>>>>> necessitate removal of the first element of the right
>>>>>>>>> std::vector.
>>>>>>>>
>>>>>>>> I don't think that this applies to the way that I implemented
>>>>>>>> it. pop_front pops from the end of Left. pop_back pops from
>>>>>>>> the end of Right. This is the key aspect that I used from
>>>>>>>> David's two-stack approach.
>>>>>>>
>>>>>>> Then it is totally different to what std::deque offers:
>>>>>>> std::deque allows ALL elements to be either popped from the
>>>>>>> front or back. Try reading AND UNDERSTANDING what I wrote again.
>>>>>>>
>>>>>>> /Flibble
>>>>>>>
>>>>>>
>>>>>> I could allow all elements to be popped from the front or the
>>>>>> back too. Mine is much faster when you need far less than all
>>>>>> elements.
>>>>>
>>>>> What you have does not offer what std::deque offers so is not
>>>>
>>>> All these things can be added and we end up with a simple, faster,
>>>> std:deque that has most the conventional overhead and complexity
>>>> abolished.
>>>>
>>>>> equivalent to std::deque so can't be considered better than
>>>>> std::deque for the general case (I don't care about your specific
>>>>> use-case).
>>>>>
>>>>> /Flibble
>>>>>
>>>>
>>>> It just a matter of defining more member functions.
>>>
>>> You cannot implement all of std::deque's member functions meeting
>>> std::deque requirements using your chosen data structure of two
>>> std::vectors.
>>>
>>> /Flibble
>>>
>>
>> // Tape_Type implements a two-way Turing machine tape.
>> // Right contains Tape_Head >= 0 values (right expansion)
>> // Left contains Tape_Head < 0 values (left expansion)
>> //
>> // Grows with Right.push_back() as Tape_Head increases above 0.
>> // Grows with Left.push_back() as Tape_Head decreases below 0.
>> //
>> // Tape_Type has functionality very similar to std::deque
>> // yet implements this functionality much more simply.
>> // This saves time and space.
>> //
>> class Tape_Type
>> {
>> public:
>> typedef unsigned char tape_element;
>>
>> private:
>> int Tape_Head = 0; // Can be negative
>> std::vector<tape_element> Left; // Stores left expansion
>> std::vector<tape_element> Right; // Stores right expansion
>>
>> tape_element& operator[](int index)
>> {
>> return index >= 0 ? Right[index] : Left[-index - 1];
>> }
>>
>> public:
>> tape_element& front( ) { return Left.back(); }
>> tape_element& back() { return Right.back(); }
>> void pop_front() { Left.pop_back(); }
>> void pop_back() { Right.pop_back(); }
>> void push_front(tape_element& E) { Left.push_back(E); }
>> void push_back(tape_element& E) { Right.push_back(E); }
>> void reserve(unsigned int N)
>> { Left.reserve(N); Right.reserve(N); }
>
> And what happens if Left is empty, Right is non-empty and you call
> pop_front()?
Flip a coin; heads left, tails right.
Heads, try to pop from left.
Tails, try to pop from right.
Just joking around here, in a sense... ;^)
Actually, back in the day with my threading work, I have subdivided a
lock-free stack into regions to amortize things. It was nothing like a
deque. It was a long time ago, damn near 20 years. The cool part was
that multiple threads could push/pop items without interfering with one
another in a lot of use cases that respected locality. It was layered up:
per-thread container
hash bucket container
global container
Iirc, to pop an element from the container:
check per-thread
check hash bucket
check the global
if all checks fail, return nullptr, if not return the popped node.
I think I might still have this code on an old hard drive.
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2022-05-12 19:23 -0400 |
| Message-ID | <5GgfK.2451$R6W6.1148@fx45.iad> |
| In reply to | #50308 |
On 5/12/22 6:51 PM, olcott wrote:
> C/C++ people please critique this as the basis for an improvement to
> std::deque. It seems to have the key functionality of std::deque and
> does it much more simply while saving time and space.
> https://www.cplusplus.com/reference/deque/deque/
>
> #define tape_element unsigned char
>
> class Tape_Type
> {
> private:
> int Tape_Head = 0; // Can be negative
> std::vector<tape_element> Left; // Stores left expansion
> std::vector<tape_element> Right; // Stores right expansion
> tape_element & operator[](int index);
>
> public:
> void move_left(); // Tape_Head--; Left.push_back(0); as needed
> void move_right(); // Tape_Head++; Left.push_back(0); as needed
> void Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
> tape_element Read() { return this->operator[](Tape_Head); };
> Tape_Type(){ Right.push_back('_'); } // constructor
> void Output();
> };
>
> tape_element& Tape_Type::operator[](int index)
> {
> if (index > 0)
> return Right[index];
> int Left_Index = ((index * -1) -1);
> return Left[Left_Index];
> }
>
> void Tape_Type::Output()
> {
> printf("Tape_Type::Output()\n");
>
> if (Left.size())
> {
> int Last_One = Left.size() - 1;
> for (int N = Last_One; N >= 0; N--)
> {
> int TH = (N + 1) * -1; // determine Tape_Head from N
> printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
> }
> }
> if (Right.size())
> for (int N = 0; N < Right.size(); N++)
> printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
> }
>
> void Tape_Type::move_left()
> {
> Tape_Head--;
> int Left_Index = ((Tape_Head * -1) -1);
> if (Left_Index == Left.size())
> Left.push_back('_');
> }
>
> void Tape_Type::move_right()
> {
> Tape_Head++;
> if (Tape_Head == Right.size())
> Right.push_back('_');
> }
>
>
>
Looks at what indexing with an index value of 0 does.
Operator [] want to test index >= 0, not > 0
[toc] | [prev] | [next] | [standalone]
| From | olcott <NoOne@NoWhere.com> |
|---|---|
| Date | 2022-05-12 18:32 -0500 |
| Message-ID | <Up-dnYjT5e-2BOD_nZ2dnUU7_8zNnZ2d@giganews.com> |
| In reply to | #50319 |
On 5/12/2022 6:23 PM, Richard Damon wrote:
> On 5/12/22 6:51 PM, olcott wrote:
>> C/C++ people please critique this as the basis for an improvement to
>> std::deque. It seems to have the key functionality of std::deque and
>> does it much more simply while saving time and space.
>> https://www.cplusplus.com/reference/deque/deque/
>>
>> #define tape_element unsigned char
>>
>> class Tape_Type
>> {
>> private:
>> int Tape_Head = 0; // Can be negative
>> std::vector<tape_element> Left; // Stores left expansion
>> std::vector<tape_element> Right; // Stores right expansion
>> tape_element & operator[](int index);
>>
>> public:
>> void move_left(); // Tape_Head--; Left.push_back(0); as needed
>> void move_right(); // Tape_Head++; Left.push_back(0); as needed
>> void Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
>> tape_element Read() { return this->operator[](Tape_Head); };
>> Tape_Type(){ Right.push_back('_'); } // constructor
>> void Output();
>> };
>>
>> tape_element& Tape_Type::operator[](int index)
>> {
>> if (index > 0)
>> return Right[index];
>> int Left_Index = ((index * -1) -1);
>> return Left[Left_Index];
>> }
>>
>> void Tape_Type::Output()
>> {
>> printf("Tape_Type::Output()\n");
>>
>> if (Left.size())
>> {
>> int Last_One = Left.size() - 1;
>> for (int N = Last_One; N >= 0; N--)
>> {
>> int TH = (N + 1) * -1; // determine Tape_Head from N
>> printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
>> }
>> }
>> if (Right.size())
>> for (int N = 0; N < Right.size(); N++)
>> printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
>> }
>>
>> void Tape_Type::move_left()
>> {
>> Tape_Head--;
>> int Left_Index = ((Tape_Head * -1) -1);
>> if (Left_Index == Left.size())
>> Left.push_back('_');
>> }
>>
>> void Tape_Type::move_right()
>> {
>> Tape_Head++;
>> if (Tape_Head == Right.size())
>> Right.push_back('_');
>> }
>>
>>
>>
>
> Looks at what indexing with an index value of 0 does.
>
> Operator [] want to test index >= 0, not > 0
Good catch. I just wrote that function as a simplification.
--
Copyright 2022 Pete Olcott
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
[toc] | [prev] | [next] | [standalone]
| From | Ben <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2022-05-13 01:06 +0100 |
| Message-ID | <87wneq1ejm.fsf@bsb.me.uk> |
| In reply to | #50308 |
olcott <NoOne@NoWhere.com> writes:
I've removed the philosophy group and comp.lang.c as this is C++.
> C/C++ people please critique this as the basis for an improvement to
> std::deque.
You will get critiques of the code on whatever basis people feel
inclined to comment! You can't limit the comments to some particular
context.
> It seems to have the key functionality of std::deque and
> does it much more simply while saving time and space.
It does not have any of the functionality of std::deque. There is a
commonly used (though not particularly efficient) way to implement a
deque using two arrays, but this is not it.
> #define tape_element unsigned char
Use a typedef or using declaration. Also, I'd put the typedef in the
class as the type belongs to the class (as least that appears to be the
case from the name you've chosen).
> class Tape_Type
> {
> private:
> int Tape_Head = 0; // Can be negative
> std::vector<tape_element> Left; // Stores left expansion
> std::vector<tape_element> Right; // Stores right expansion
> tape_element & operator[](int index);
>
> public:
> void move_left(); // Tape_Head--; Left.push_back(0); as needed
> void move_right(); // Tape_Head++; Left.push_back(0); as needed
The comments are wrong since you push_back('_').
> void Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
> tape_element Read() { return this->operator[](Tape_Head); };
I'd write (*this)[Tape_Head] but I suppose that's just a matter of style.
> Tape_Type(){ Right.push_back('_'); } // constructor
The constructor leaves a Tape_Type object in an unusable state, but
that's due to a bug in operator[]. Did you test?
> void Output();
> };
>
> tape_element& Tape_Type::operator[](int index)
> {
> if (index > 0)
> return Right[index];
Bug. You meant index >= 0 I think.
> int Left_Index = ((index * -1) -1);
Why not -index - 1?
> return Left[Left_Index];
Do you think introducing a new variable really make the code clearer
that simply writing
return Left[-index - 1];
? Personally, I'd write the whole thing as
return index >= 0 ? Right[index] : Left[-index - 1];
> }
>
> void Tape_Type::Output()
> {
> printf("Tape_Type::Output()\n");
>
> if (Left.size())
> {
> int Last_One = Left.size() - 1;
> for (int N = Last_One; N >= 0; N--)
> {
> int TH = (N + 1) * -1; // determine Tape_Head from N
> printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
> }
> }
> if (Right.size())
> for (int N = 0; N < Right.size(); N++)
> printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
> }
>
> void Tape_Type::move_left()
> {
> Tape_Head--;
> int Left_Index = ((Tape_Head * -1) -1);
> if (Left_Index == Left.size())
> Left.push_back('_');
> }
>
> void Tape_Type::move_right()
> {
> Tape_Head++;
> if (Tape_Head == Right.size())
> Right.push_back('_');
> }
I find the capitalisation odd and unhelpful as there does not seem to be
any consistency about it.
--
Ben.
"le génie humain a des limites, quand la bêtise humaine n’en a pas"
Alexandre Dumas (fils)
[toc] | [prev] | [next] | [standalone]
| From | olcott <NoOne@NoWhere.com> |
|---|---|
| Date | 2022-05-12 19:55 -0500 |
| Message-ID | <MeOdncpeZacPMeD_nZ2dnUU7_8zNnZ2d@giganews.com> |
| In reply to | #50329 |
On 5/12/2022 7:06 PM, Ben wrote:
> olcott <NoOne@NoWhere.com> writes:
>
> I've removed the philosophy group and comp.lang.c as this is C++.
>
>> C/C++ people please critique this as the basis for an improvement to
>> std::deque.
>
> You will get critiques of the code on whatever basis people feel
> inclined to comment! You can't limit the comments to some particular
> context.
>
>> It seems to have the key functionality of std::deque and
>> does it much more simply while saving time and space.
>
> It does not have any of the functionality of std::deque.
That is a ridiculously stupid thing to say. It has the key most
important functionality of a std:deque
Double ended queue
deque (usually pronounced like "deck") is an irregular acronym of
double-ended queue. Double-ended queues are sequence containers with
dynamic sizes that can be expanded or contracted on both ends (either
its front or its back).
All of the rest of the functionality of std::deque can be added as needed.
> There is a
> commonly used (though not particularly efficient) way to implement a
> deque using two arrays, but this is not it.
>
>> #define tape_element unsigned char
>
> Use a typedef or using declaration. Also, I'd put the typedef in the
> class as the type belongs to the class (as least that appears to be the
> case from the name you've chosen).
>
>> class Tape_Type
>> {
>> private:
>> int Tape_Head = 0; // Can be negative
>> std::vector<tape_element> Left; // Stores left expansion
>> std::vector<tape_element> Right; // Stores right expansion
>> tape_element & operator[](int index);
>>
>> public:
>> void move_left(); // Tape_Head--; Left.push_back(0); as needed
>> void move_right(); // Tape_Head++; Left.push_back(0); as needed
>
> The comments are wrong since you push_back('_').
>
>> void Write(tape_element Y){ this->operator[](Tape_Head) = Y; };
>> tape_element Read() { return this->operator[](Tape_Head); };
>
> I'd write (*this)[Tape_Head] but I suppose that's just a matter of style.
>
>> Tape_Type(){ Right.push_back('_'); } // constructor
>
> The constructor leaves a Tape_Type object in an unusable state, but
> that's due to a bug in operator[]. Did you test?
>
Yes I tested so I don't see what you mean.
>> void Output();
>> };
>>
>> tape_element& Tape_Type::operator[](int index)
>> {
>> if (index > 0)
>> return Right[index];
>
> Bug. You meant index >= 0 I think.
Yes Richard caught that. That was a new refactoring.
>
>> int Left_Index = ((index * -1) -1);
>
> Why not -index - 1?
>
>> return Left[Left_Index];
>
> Do you think introducing a new variable really make the code clearer
> that simply writing
>
> return Left[-index - 1];
>
> ? Personally, I'd write the whole thing as
>
> return index >= 0 ? Right[index] : Left[-index - 1];
>
>> }
>>
>> void Tape_Type::Output()
>> {
>> printf("Tape_Type::Output()\n");
>>
>> if (Left.size())
>> {
>> int Last_One = Left.size() - 1;
>> for (int N = Last_One; N >= 0; N--)
>> {
>> int TH = (N + 1) * -1; // determine Tape_Head from N
>> printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
>> }
>> }
>> if (Right.size())
>> for (int N = 0; N < Right.size(); N++)
>> printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
>> }
>>
>> void Tape_Type::move_left()
>> {
>> Tape_Head--;
>> int Left_Index = ((Tape_Head * -1) -1);
>> if (Left_Index == Left.size())
>> Left.push_back('_');
>> }
>>
>> void Tape_Type::move_right()
>> {
>> Tape_Head++;
>> if (Tape_Head == Right.size())
>> Right.push_back('_');
>> }
>
> I find the capitalisation odd and unhelpful as there does not seem to be
> any consistency about it.
>
I found all of your suggestions very helpful.
I don't see the bug in the constructor.
I like mixed case because it is easier to read, mine not be consistent.
Here they are implemented.
//
// Tape_Type implements a two-way Turing machine tape.
// Right contains Tape_Head >= 0 values (right expansion)
// Left contains Tape_Head < 0 values (left expansion)
//
// Tape_Type has functionality very similar to std::deque
// yet implements this functionality much more simply.
// This saves time and space.
//
class Tape_Type
{
typedef unsigned char tape_element;
private:
int Tape_Head = 0; // Can be negative
std::vector<tape_element> Left; // Stores left expansion
std::vector<tape_element> Right; // Stores right expansion
tape_element& operator[](int index)
{
return index >= 0 ? Right[index] : Left[-index - 1];
}
public:
Tape_Type(){ Right.push_back('_'); } // constructor
void Write(tape_element Y){ (*this)[Tape_Head] = Y; };
tape_element Read() { return (*this)[Tape_Head]; };
void move_left()
{
Tape_Head--;
int Left_Index = ((Tape_Head * -1) -1);
if (Left_Index == Left.size())
Left.push_back('_');
}
void move_right()
{
Tape_Head++;
if (Tape_Head == Right.size())
Right.push_back('_');
}
void Output()
{
printf("Tape_Type::Output()\n");
if (Left.size())
{
int Last_One = Left.size() - 1;
for (int N = Last_One; N >= 0; N--)
{
int TH = (N + 1) * -1; // determine Tape_Head from N
printf("[%04d]:%c Left[%02d]\n", TH, Left[N], N);
}
}
if (Right.size())
for (int N = 0; N < Right.size(); N++)
printf("[%04d]:%c Right[%02d]\n", N, Right[N], N);
}
};
--
Copyright 2022 Pete Olcott
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.theory
csiph-web