Question: Hi I'm doing a coding challenge and I'm trying to fetch data from an html page but I keep getting the 400 error. I don't see where my syntax would be wrong. The Promise returns an empty string as PromiseResult. Why do I not get the data from <https://adventofcode.com/2021/day/2/input>?

```
fetch('https://adventofcode.com/2021/day/2/input', {
    method: 'GET',
    mode: 'no-cors', 
    credentials: 'omit',
    headers: {
      'Content-Type': 'text/plain'
    } 
  })
    .then((response) => { 
      response.text();
    })
    .then((html) => {
      var parser = new DOMParser();
        var doc = parser.parseFromString(html, 'text/html');
    })
    .catch((err) => { console.log(err) })

```

Answer: 
This is ~33% faster (for the data given):

```
def index_last_value2(tbl, get_val=lambda obj:obj):
    prev_v = get_val(tbl[-1])
    for i in range(len(tbl) - 2, -1, -1):
        if get_val(tbl[i]) != prev_v:
            return i + 1
    return 0

```

You could get another ~15% of speepdup by changing argument `get_val` function into name of attribute:

```
def index_last_value3(tbl, val_name):
    prev_v = tbl[-1].__dict__[val_name]
    for i in range(len(tbl) - 2, -1, -1):
        if tbl[i].__dict__[val_name] != prev_v:
            return i + 1
    return 0
index_last_value3(tbl_1, val_name='v')
index_last_value3(tbl_2, val_name='v')

```

Profiling in reverse order to make sure RAM operations do not favor optimized versions:

```
    44      1001       2682.0      2.7      3.8      for _ in range(1000):
    45      1000       6420.0      6.4      9.1          index_last_value3(tbl_1, val_name='v')
    46      1000       7857.0      7.9     11.1          index_last_value3(tbl_2, val_name='v')
    47      1001       2745.0      2.7      3.9      for _ in range(1000):
    48      1000       7676.0      7.7     10.9          index_last_value2(tbl_1, get_val=lambda obj: obj.v)
    49      1000      10370.0     10.4     14.7          index_last_value2(tbl_2, get_val=lambda obj:obj.v)
    50      1001       2670.0      2.7      3.8      for _ in range(1000):
    51      1000      12083.0     12.1     17.1          index_last_value(tbl_1, get_val=lambda obj: obj.v)
    52      1000      18007.0     18.0     25.5          index_last_value(tbl_2, get_val=lambda obj: obj.v)

```
**General answer**

We scan the list from its beginning to its end

```
def index_last_value(tbl, get_val=lambda obj:obj):
    lastv = get_val(tbl[-1])
    for i,v in enumerate(tbl):
        if get_val(v) == lastv:
            return i

```

**Special case** : the values are contiguous (ie. there is no gap) :
[1, 1, 2, 2, 2] is possible, [1, 1, 2, 3, 2] is not.

We scan the list from end to its beginning,

We could reverse the list but we can also do without reversing it:

```
def index_last_value(tbl, get_val=lambda obj:obj):
    len_tbl = len(tbl)
    if len_tbl == 1:
        return 0
    lastv = get_val(tbl[-1])
    for i,v in enumerate(tbl[-2::-1]):
        if get_val(v) != lastv:
            return len_tbl - i - 1
    return 0

```