-
Notifications
You must be signed in to change notification settings - Fork 1
/
BinaryQueries.c
1843 lines (1612 loc) · 56.6 KB
/
BinaryQueries.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*All Tracks --> Data Structures --> Arrays --> 1-D --> Problem -->
Binary Queries
Tag(s): Very-Easy
Some problems appear hard though they are very easy. Today Aakash is stuck in a range query problem. He has been given an array with only numbers 0 and 1.
There are two types of queries -
0 L R : Check whether the number formed from the array elements L to R is even or odd and print EVEN or ODD respectively.
Number formation is the binary number from the bits status in the array L to R
1 X : Flip the Xth bit in the array
Indexing is 1 based
Input
First line contains a number N and Q as input. Next line contains N space separated 0 or 1. Next Q lines contain description of each query
Output
Output for only query type 0 L R whether the number in range L to R is "EVEN" or "ODD" (without quotes).
Constraints
1<= N <= 10^6
1<= L <= R <= 10^6
1<= Q <= 10^6
1<= X <= N
SAMPLE INPUT
5 2
1 0 1 1 0
1 2
0 1 4
SAMPLE OUTPUT
ODD
Explanation
Our first query is 1 2 that means that we have to flip the 2nd bit in the given array so now our array becomes 1 1 1 1 0
2nd query is 0 1 4 which means that if i pick the subarray 1 to 4 i.e 1 1 1 1 then the number formed by decimal representation of this binary number is of what kind ?.
Here the number formed is 15 so its odd and ODD is the output
// My C Solution:
#include <stdio.h>
#define LEN 1000001
#define FLIP 1
#define PARITY 0
int main(){
int Q,Qtype,n,L,R,i,pos,num[LEN];
scanf("%d%d",&n,&Q);
for(i=0;i<n;i++)
scanf("%d",&num[i]);
while(Q--){
scanf("%d",&Qtype);
if(Qtype == FLIP){
scanf("%d",&pos);
num[(pos-1)]^=1; //Flip bit at pos using XOR mask(1)
}
else if(Qtype == PARITY){
scanf("%d%d",&L,&R);
printf(num[(R-1)] == 1 ? "ODD\n" : "EVEN\n");
}
}
return 0;
}
*/
/*Best Submissions:
C:
#include <stdio.h>
void scnaf_leave_int(int *n)
{
register int c = getchar_unlocked();
for( ; (c<48 || c>57); c = getchar_unlocked() );
for( ; (c>47 && c<58); c = getchar_unlocked() );
}
void scnaf_int(int *n){
register int c = getchar_unlocked();
*n = 0;
for( ; (c<48 || c>57); c = getchar_unlocked() );
for( ; (c>47 && c<58); c = getchar_unlocked() ){
*n = (*n<<1) + (*n<<3) +c -48;
}
}
//getchar_unlocked() is a function which scans input much faster than scanf. It reads input as char. And it is converted to int by shift operations and "- 48".
int main()
{
int i,n,q,a;
scnaf_int(&n);
scnaf_int(&q);
int arr[n+1];
for(i=1; i<=n; i++)
scnaf_int(&arr[i]);
while(q--){
scnaf_int(&a);
if(a==1){
int x;
scnaf_int(&x);
arr[x] = !arr[x];
}
else if(a==0){
int l,r;
scnaf_leave_int(&l);
scnaf_int(&r);
if(arr[r]==1)
printf("ODD\n");
else
printf("EVEN\n");
}
}
return 0;
}
C++:
#include <iostream>
using namespace std;
int scan(){
register int c = getchar_unlocked();
int n = 0;
for( ; (c<48 || c>57); c = getchar_unlocked() );
for( ; (c>47 && c<58); c = getchar_unlocked() ){
n = (n<<1) + (n<<3) +c -48;
}
return n;
}
void scan1(){
register int c = getchar_unlocked();
for( ; (c<48 || c>57); c = getchar_unlocked() );
for( ; (c>47 && c<58); c = getchar_unlocked() );
}
int main()
{
int n,q;
n=scan();
q=scan();
//cin>>n>>q;
int a[n];
int i,j;
int x,l,r;
for(i=0;i<n;i++) a[i]=scan();
while(q){
x=scan();
if(x==1){
l=scan();
//cin>>l;
a[l-1]=(a[l-1]+1)%2;
}
else {
scan1();
r=scan();
//cin>>l>>r;
if(a[r-1]==1) printf("ODD\n");
else if(a[r-1]==0) printf("EVEN\n");
}
q--;
}
return 0;
}
C++14:
#include <iostream>
#include <cstdio>
using namespace std;
int bit_arr[1000002]={0};
int scan(){ // not thread safe
register int c = getchar_unlocked();
register int n = 0;
for( ; (c<48 || c>57); c = getchar_unlocked() ); // not thread safe
for( ; (c>47 && c<58); c = getchar_unlocked() ){
n = (n<<1) + (n<<3) +c -48;
}
return n;
}
int main(){
int N,Q;
scanf("%d %d", &N, &Q);
int L, R, q;
// for(int i=1;i<=N;++i) scanf("%d ", &bit_arr[i]);
for(int i=1;i<=N;++i) bit_arr[i] = scan();
for(int i=0;i<Q;++i){
// scanf("%d ", &q);
q = scan();
if(q==0){
// scanf("%d %d", &L, &R);
L = scan();
R = scan();
if(bit_arr[R]==0) printf("EVEN\n");
else printf("ODD\n");
}else{
// scanf("%d ", &q);
q = scan();
bit_arr[q] = 1 - bit_arr[q];
}
}
return 0;
}
C#:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace HackerEarth
{
/// <summary>
/// Solution class
/// </summary>
internal static class Program
{
#region Main
/// <summary>
/// Fast Console IO helper
/// </summary>
private static readonly ConsoleHelper console = new ConsoleHelper();
/// <summary>
/// Main method - Launches solver
/// </summary>
private static void Main()
{
//Depending on problem
using (console)
{
//TestCases();
Solve();
}
}
/// <summary>
/// Solves the problem for multiple test cases
/// </summary>
private static void TestCases()
{
int n = console.NextInt();
console.NextLine();
for (int i = 0; i < n; i++)
{
Solve();
}
}
#endregion
#region Solution
/// <summary>
/// Solution
/// </summary>
private static void Solve()
{
int n = console.NextInt(), m = console.NextInt();
console.SkipNextLine();
bool[] bits = new bool[n + 1];
for (int i = 1; i <= n; i++)
{
bits[i] = console.Read() == 49;
console.Skip();
}
console.Skip();
for (int i = 0; i < m; i++)
{
if (console.Read() == 49)
{
bits[console.NextInt()] ^= true; //Flips the bool
}
else
{
console.SkipNext();
console.WriteLine(bits[console.NextInt()] ? "ODD" : "EVEN");
}
console.SkipNextLine();
}
}
#endregion
}
/// <summary>
/// Fast Console IO helper
/// </summary>
internal sealed class ConsoleHelper : IDisposable
{
#region Constants
/// <summary>
/// The standard input and output buffers size (2^20, 1Mb)
/// </summary>
private const int baseSize = 1048576;
#endregion
#region Fields
private readonly BufferedStream inStream; //Buffered console input stream
private readonly BufferedStream outStream; //Buffered console output stream
private readonly byte[] inBuffer; //Input buffer
private readonly byte[] outBuffer; //Output buffer
private int inputIndex; //Input buffer current index
private int outputIndex; //Output buffer current index
private int bufferEnd; //Input buffer ending index
#endregion
#region Properties
/// <summary>
/// The buffer size, in bytes
/// </summary>
public int BufferSize { get; }
/// <summary>
/// If this memory stream is open and available to read/write
/// </summary>
public bool Open { get; private set; }
#endregion
#region Constructors
/// <summary>
/// Creates a new console IO helper reading from the standard Console input and output
/// </summary>
public ConsoleHelper() : this(baseSize) { }
/// <summary>
/// Creates a new console IO helper reading from the standard Console input and output with the specified buffer size
/// <param name="bufferSize">Size of the buffer to use in bytes</param>
/// </summary>
public ConsoleHelper(int bufferSize)
{
//Open the input stream
this.inStream = new BufferedStream(Console.OpenStandardInput(bufferSize), bufferSize); //Submission stream
//this.inStream = new BufferedStream(File.OpenRead(@"..\..\test.txt"), bufferSize); //Test stream
this.inBuffer = new byte[bufferSize];
//Open the output stream
this.outStream = new BufferedStream(Console.OpenStandardOutput(bufferSize), bufferSize);
this.outBuffer = new byte[bufferSize];
//Set fields
this.inputIndex = this.outputIndex = this.bufferEnd = 0;
this.BufferSize = bufferSize;
this.Open = true;
}
#endregion
#region Static methods
/// <summary>
/// Verifies that the passed character is a non-special ASCII character
/// </summary>
/// <param name="i">Character to validate</param>
/// <returns>True if the character is not a special character</returns>
public static bool ValidateChar(int i) => i >= ' ';
/// <summary>
/// Verifies that the passed character is a non-special ASCII character or a whitespace
/// </summary>
/// <param name="i">Character to validate</param>
/// <returns>True if the character is not a whitespace or a special character</returns>
public static bool ValidateCharNoSpace(int i) => i > ' ';
/// <summary>
/// Verifies that the passed character is a numerical character (0-9)
/// </summary>
/// <param name="i">Character to validate</param>
/// <returns>True if the character is a numerical character, false otherwise</returns>
public static bool ValidateNumber(int i) => i >= '0' && i <= '9';
/// <summary>
/// Verifies if a character is an Endline character
/// </summary>
/// <param name="i">Character to check</param>
/// <returns>True if it is an Endline character, false otherwise</returns>
public static bool IsEndline(int i) => i == '\n' || i == '\0';
#endregion
#region Methods
/// <summary>
/// Returns the next byte data in the console input stream
/// </summary>
/// <returns>Next data byte from the console</returns>
public byte Read()
{
CheckBuffer();
return this.inBuffer[this.inputIndex++];
}
/// <summary>
/// Returns the next byte data in the console input stream without consuming it
/// </summary>
/// <returns>Next data byte from the console</returns>
public byte Peek()
{
CheckBuffer();
return this.inBuffer[this.inputIndex];
}
/// <summary>
/// Skips a number of characters in the input stream
/// </summary>
/// <param name="n">Amount of chars to skip, defaults to 1</param>
public void Skip(int n = 1) => this.inputIndex += n;
/// <summary>
/// Assures we have data available in the input buffer
/// </summary>
private void CheckBuffer()
{
//If we reach the end of the buffer, load more data
if (this.inputIndex >= this.bufferEnd)
{
this.inputIndex = this.inputIndex - this.bufferEnd;
this.bufferEnd = this.inStream.Read(this.inBuffer, 0, this.BufferSize);
//If nothing was added, add a null char at the start
if (this.bufferEnd < 1) { this.inBuffer[this.bufferEnd++] = 0; }
}
}
/// <summary>
/// Returns the next character in the console input stream
/// </summary>
/// <returns>Next character in the input stream</returns>
public char NextChar() => (char)Read();
/// <summary>
/// Returns the next string token from the console input
/// </summary>
/// <exception cref="InvalidOperationException">If there is no more data on the line being read</exception>
/// <returns>Parsed string, separated by spaces or special characters such as line feeds</returns>
public string Next()
{
byte b = SkipInvalid();
ValidateEndline(b);
//Append all characters
StringBuilder sb = new StringBuilder().Append((char)b);
b = Peek();
while (ValidateCharNoSpace(b))
{
//Peek to not consume terminator
sb.Append((char)b);
Skip();
b = Peek();
}
return sb.ToString();
}
/// <summary>
/// Returns the next int value in the console input, this is a fast parse
/// </summary>
/// <exception cref="FormatException">If the text is not a valid integer</exception>
/// <exception cref="InvalidOperationException">If there is no more data on the line being read</exception>
/// <exception cref="OverflowException">If the value is too large for integer</exception>
/// <returns>Parsed int value from the input</returns>
public int NextInt()
{
//Skip invalids
byte b = SkipInvalid();
ValidateEndline(b);
//Verify for negative
bool neg = false;
if (b == '-')
{
neg = true;
b = Read();
}
//Get first digit
if (!ValidateNumber(b)) { throw new FormatException("Integer parsing has failed because the string contained invalid characters"); }
int n = b - '0';
b = Peek();
while (ValidateNumber(b))
{
//Peek to not consume terminator, and check for overflow
n = checked((n << 3) + (n << 1) + (b - '0'));
Skip();
b = Peek();
}
//If the character causing the exit is a valid ASCII character, the integer isn't correct formatted
if (ValidateCharNoSpace(b)) { throw new FormatException("Integer parsing has failed because the string contained invalid characters"); }
return neg ? -n : n;
}
/// <summary>
/// Returns the next long value in the console input, this is a fast parse
/// </summary>
/// <exception cref="FormatException">If the text is not a valid long</exception>
/// <exception cref="InvalidOperationException">If there is no more data on the line being read</exception>
/// <exception cref="OverflowException">If the value is too large for long</exception>
/// <returns>Parsed long value from the input</returns>
public long NextLong()
{
byte b = SkipInvalid();
ValidateEndline(b);
//Verify negative
bool neg = false;
if (b == '-')
{
neg = true;
b = Read();
}
//Get first digit
if (!ValidateNumber(b)) { throw new FormatException("Integer parsing has failed because the string contained invalid characters"); }
long n = b - '0';
b = Peek();
while (ValidateNumber(b))
{
//Peek to not consume terminator, and check for overflow
n = checked((n << 3) + (n << 1) + (b - '0'));
Skip();
b = Peek();
}
//If the character causing the exit is a valid ASCII character, the long isn't correct formatted
if (ValidateCharNoSpace(b)) { throw new FormatException("Long parsing has failed because the string contained invalid characters"); }
return neg ? -n : n;
}
/// <summary>
/// Returns the next double value in the console input
/// Note: fast double parsing is slightly harder, I'll implement it if I need to
/// </summary>
/// <exception cref="FormatException">If the text is not a valid double</exception>
/// <exception cref="InvalidOperationException">If there is no more data on the line being read</exception>
/// <exception cref="OverflowException">If the value is too large for double</exception>
/// <returns>Parsed double value from the input</returns>
public double NextDouble() => double.Parse(Next());
/// <summary>
/// Returns the next n int values on the same line in an array
/// </summary>
/// <param name="n">Number of values to seek</param>
/// <exception cref="FormatException">If the text is not a valid integer</exception>
/// <exception cref="InvalidOperationException">If there is no more data on the line being read</exception>
/// <exception cref="OverflowException">If the value is too large for integer</exception>
/// <exception cref="OutOfMemoryException">If the created array is too large for the system memory</exception>
/// <returns>The n integer values in an array</returns>
public int[] NextInts(int n)
{
int[] array = new int[n];
for (int i = 0; i < n; i++)
{
array[i] = NextInt();
}
NextLine();
return array;
}
/// <summary>
/// Returns the next n int values on the next m lines in the output stream under the form of an NxM matrix
/// </summary>
/// <param name="n">Number of rows to the matrix</param>
/// <param name="m">Number of columns to the matrix</param>
/// <exception cref="FormatException">If the text is not a valid integer</exception>
/// <exception cref="InvalidOperationException">If there is no more data on the line being read</exception>
/// <exception cref="OverflowException">If the value is too large for integer</exception>
/// <exception cref="OutOfMemoryException">If the created 2D array is too large for the system memory</exception>
/// <returns>The NxM matrix of integers</returns>
public int[,] NextMatrix(int n, int m)
{
int[,] matrix = new int[n, m];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i, j] = NextInt();
}
NextLine();
}
return matrix;
}
/// <summary>
/// Returns the next line of text in the console
/// </summary>
/// <returns>Next string line from the console</returns>
public string NextLine()
{
byte b = SkipInvalid();
if (b == 0)
{
//Consume newline and return empty string
Skip();
return string.Empty;
}
//Read all the characters until the next linefeed
StringBuilder sb = new StringBuilder().Append((char)b);
b = Read();
while (!IsEndline(b))
{
//Don't append special characters, but don't exit
if (ValidateChar(b))
{
sb.Append((char)b);
}
b = Read();
}
return sb.ToString();
}
/// <summary>
/// Skips the next token in input
/// </summary>
/// <exception cref="InvalidOperationException">If there is no more data on the line being read</exception>
public void SkipNext()
{
byte b = SkipInvalid();
ValidateEndline(b);
for (b = Peek(); ValidateCharNoSpace(b); b = Peek())
{
Skip();
}
}
/// <summary>
/// Skips all the text on the current line and jump to the next
/// </summary>
public void SkipNextLine()
{
for (byte b = Read(); !IsEndline(b); b = Read()) { }
}
/// <summary>
/// Enumerates the given number of integers on the current line
/// </summary>
/// <param name="n">Number of integers on the current line</param>
/// <returns>Enumerable of the integers</returns>
public IEnumerable<int> EnumerateInts(int n)
{
while (n-- > 0)
{
yield return NextInt();
}
NextLine();
}
/// <summary>
/// Enumerates all the characters in the next line until the feed is exhausted or an endline character is met
/// </summary>
/// <returns>Enumerable of all the characters in the current line</returns>
public IEnumerable<char> EnumerateLine()
{
for (char c = NextChar(); !IsEndline(c); c = NextChar())
{
if (ValidateChar(c))
{
yield return c;
}
}
}
/// <summary>
/// Assures we are not trying to read more data on the line that there exists
/// </summary>
/// <param name="b">Byte data to verify</param>
/// <exception cref="InvalidOperationException">If there is no more data on the line being read</exception>
private void ValidateEndline(byte b)
{
//If empty char
if (b == 0)
{
//Go back a char and throw
this.inputIndex--;
throw new InvalidOperationException("No values left on line");
}
}
/// <summary>
/// Skips all invalid character bytes then returns the first valid byte found, spaces are considered invalid
/// </summary>
/// <returns>The next valid character byte, cannot be a whitespace</returns>
private byte SkipInvalid()
{
byte b = Peek();
if (IsEndline(b)) { return 0; }
while (!ValidateCharNoSpace(b))
{
Skip();
b = Peek();
//Return empty char if we meet an linefeed or empty char
if (IsEndline(b)) { return 0; }
}
return Read();
}
/// <summary>
/// Writes the given char to the console output
/// </summary>
/// <param name="c">Character to write</param>
public void Write(char c) => WriteByte((byte)c);
/// <summary>
/// Writes the given char buffer to the console output
/// </summary>
/// <param name="buffer">Char buffer to write</param>
public void Write(char[] buffer) => buffer.ForEach(c => WriteByte((byte)c));
/// <summary>
/// Writes the given string to the console output
/// </summary>
/// <param name="s">String to write</param>
public void Write(string s) => Write(s.ToCharArray());
/// <summary>
/// Writes the given integer to the console output
/// </summary>
/// <param name="n">Integer to write</param>
public void Write(int n) => Write(n.ToString().ToCharArray());
/// <summary>
/// Writes the given long to the console output
/// </summary>
/// <param name="n">Long to write</param>
public void Write(long n) => Write(n.ToString().ToCharArray());
/// <summary>
/// Writes the given object to the console output using the object's ToString method
/// </summary>
/// <param name="o">Object to write</param>
public void Write(object o) => Write(o.ToString().ToCharArray());
/// <summary>
/// Writes a sequence to the console output with the given string separator
/// </summary>
/// <typeparam name="T">Type of elements in the sequence</typeparam>
/// <param name="e">Sequence to print</param>
/// <param name="separator">String separator between each element, defaults to the empty string</param>
public void Write<T>(IEnumerable<T> e, string separator = "") => Write(e.Join(separator).ToCharArray());
/// <summary>
/// Writes a linefeed to the console output
/// </summary>
public void WriteLine() => WriteByte(10);
/// <summary>
/// Writes the given char to the console output, followed by a linefeed
/// </summary>
/// <param name="c">Character to write</param>
public void WriteLine(char c)
{
WriteByte((byte)c);
WriteByte(10);
}
/// <summary>
/// Writes the given char buffer to the console output, followed by a linefeed
/// </summary>
/// <param name="buffer">Char buffer to write to the output</param>
public void WriteLine(char[] buffer)
{
Write(buffer);
WriteByte(10);
}
/// <summary>
/// Writes the given string to the console output, followed by a linefeed
/// </summary>
/// <param name="s">String to write</param>
public void WriteLine(string s)
{
Write(s.ToCharArray());
WriteByte(10);
}
/// <summary>
/// Writes the given integer to the console output, followed by a linefeed
/// </summary>
/// <param name="n">Integer to write</param>
public void WriteLine(int n)
{
Write(n.ToString().ToCharArray());
WriteByte(10);
}
/// <summary>
/// Writes the given long to the console output, followed by a linefeed
/// </summary>
/// <param name="n">Long to write</param>
public void WriteLine(long n)
{
Write(n.ToString().ToCharArray());
WriteByte(10);
}
/// <summary>
/// Writes a sequence to the console output with the given string separator, follows by a linefeed
/// </summary>
/// <typeparam name="T">Type of elements in the sequence</typeparam>
/// <param name="e">Sequence to print</param>
/// <param name="separator">String separator between each element, defaults to the empty string</param>
public void WriteLine<T>(IEnumerable<T> e, string separator = "")
{
Write(e, separator);
WriteByte(10);
}
/// <summary>
/// Writes the given object to the console output using the object's ToString method, followed by a linefeed
/// </summary>
/// <param name="o">Object to write</param>
public void WriteLine(object o)
{
Write(o.ToString().ToCharArray());
WriteByte(10);
}
/// <summary>
/// Writes the given data byte to the console output, this does NOT write the actual number
/// </summary>
/// <param name="b">Data byte to write</param>
public void WriteByte(byte b)
{
Flush();
this.outBuffer[this.outputIndex++] = b;
}
/// <summary>
/// Flushes the output buffer to the console if the buffer is full, or if it's being forced
/// </summary>
/// <param name="force">If the buffer must be forced to flush even if it isn't full</param>
public void Flush(bool force = false)
{
if (this.outputIndex == this.BufferSize || force)
{
this.outStream.Write(this.outBuffer, 0, this.outputIndex);
this.outStream.Flush();
this.outputIndex = 0;
}
}
/// <summary>
/// Disposes of the resources of this ConsoleHelper, closing all the associated streams
/// </summary>
public void Dispose()
{
if (this.Open)
{
Flush(true);
this.inStream.Dispose();
this.outStream.Dispose();
this.Open = false;
}
}
#endregion
}
/// <summary>
/// Useful extensions
/// </summary>
internal static class Extensions
{
#region Enumerable extensions
/// <summary>
/// Applies an action on each member of the enumerable
/// </summary>
/// <typeparam name="T">Type of elements in the Enumerable</typeparam>
/// <param name="e">Enumerable to loop through</param>
/// <param name="action">Action to apply to each parameter</param>
public static void ForEach<T>(this IEnumerable<T> e, Action<T> action)
{
foreach (T t in e)
{
action(t);
}
}
/// <summary>
/// Joins all the elements of the enumerable into a string
/// </summary>
/// <typeparam name="T">Type of elements in the Enumerable</typeparam>
/// <param name="e">Enumerable to loop through</param>
/// <param name="separator">Separator string, defaults to the empty string</param>
public static string Join<T>(this IEnumerable<T> e, string separator = "") => new StringBuilder().AppendJoin(e, separator).ToString();
/// <summary>
/// Finds the object with the maximum value in the enumerable
/// </summary>
/// <typeparam name="T">Type of objects in the Enumerable</typeparam>
/// <typeparam name="TU">Comparing type, must implement IComparable(T)</typeparam>
/// <param name="e">Enumerable to loop through</param>
/// <param name="selector">Function calculating the value that we want the max from</param>
/// <returns>The object with the maximum value in the enumerable</returns>
public static T MaxValue<T, TU>(this IEnumerable<T> e, Func<T, TU> selector) where TU : IComparable<TU>
{
using (IEnumerator<T> enumerator = e.GetEnumerator())
{
if (!enumerator.MoveNext()) { throw new InvalidOperationException("No elements in sequence"); }
T max = enumerator.Current;
TU value = selector(max);
while (enumerator.MoveNext())
{
TU v = selector(enumerator.Current);
if (value.CompareTo(v) < 0)
{
max = enumerator.Current;
value = v;
}
}
return max;
}
}
/// <summary>
/// Finds the object with the minimum value in the enumerable
/// </summary>
/// <typeparam name="T">Type of objects in the Enumerable</typeparam>
/// <typeparam name="TU">Comparing type, must implement IComparable(T)</typeparam>
/// <param name="e">Enumerable to loop through</param>
/// <param name="selector">Function calculating the value that we want the min from</param>
/// <returns>The object with the minimum value in the enumerable</returns>
public static T MinValue<T, TU>(this IEnumerable<T> e, Func<T, TU> selector) where TU : IComparable<TU>
{
using (IEnumerator<T> enumerator = e.GetEnumerator())
{
if (!enumerator.MoveNext()) { throw new InvalidOperationException("No elements in sequence"); }
T min = enumerator.Current;
TU value = selector(min);
while (enumerator.MoveNext())
{
TU v = selector(enumerator.Current);
if (value.CompareTo(v) > 0)
{
min = enumerator.Current;
value = v;
}
}
return min;
}
}
#endregion
#region String extensions
/// <summary>
/// Appends multiple objects to a StringBuilder, separated by the given string
/// </summary>
/// <typeparam name="T">Type of elements in the Enumerable</typeparam>
/// <param name="sb">StringBuilder to append to</param>
/// <param name="e">Enumerable to loop through</param>
/// <param name="separator">Separator string</param>
/// <returns>The StringBuilder instance after the appending is done</returns>
public static StringBuilder AppendJoin<T>(this StringBuilder sb, IEnumerable<T> e, string separator = "")
{
using (IEnumerator<T> enumerator = e.GetEnumerator())
{
if (enumerator.MoveNext())
{
sb.Append(enumerator.Current);
while (enumerator.MoveNext())
{
sb.Append(separator).Append(enumerator.Current);
}
}
return sb;
}
}
/// <summary>
/// Returns true if the string is null, or the empty string ""
/// Note: this will never throw a NullRef exception given that it is an extension method calling a static method
/// </summary>
/// <param name="s">String to test</param>
/// <returns>True if the string is null or empty, false otherwise</returns>
public static bool IsEmpty(this string s) => string.IsNullOrEmpty(s);
/// <summary>
/// Creates a substring from a starting and ending index
/// </summary>
/// <param name="s">String to substring</param>
/// <param name="start">Starting index</param>
/// <param name="end">Ending index</param>
/// <returns>The resulting substring</returns>
public static string SubStr(this string s, int start, int end) => s.Substring(start, (end - start) + 1);
#endregion
#region Number extensions
/// <summary>
/// Tests if the given number is pair or not
/// </summary>
/// <param name="n">Number to test</param>